Splitted jsoneditor.js and jsoneditor.css into multiple source files. Rearranged the folders a little, and updated the build script.
This commit is contained in:
parent
c5e405542e
commit
2a64d5315e
2
NOTICE
2
NOTICE
|
@ -1,7 +1,7 @@
|
|||
JSON Editor Online
|
||||
http://jsoneditoronline.org
|
||||
|
||||
Copyright (C) 2011-2012 Jos de Jong
|
||||
Copyright (C) 2011-2013 Jos de Jong
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (C) 2011-2012 Jos de Jong, http://jsoneditoronline.org
|
||||
* Copyright (C) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
* @date 2012-11-03
|
||||
* @date 2013-01-01
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -57,10 +57,10 @@
|
|||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (c) 2012 Jos de Jong, http://jsoneditoronline.org
|
||||
* Copyright (c) 2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
* @date 2012-11-03
|
||||
* @date 2013-01-01
|
||||
*/
|
||||
var FileRetriever = function (options) {
|
||||
// set options and variables
|
||||
|
|
|
@ -34,10 +34,10 @@
|
|||
License for the specific language governing permissions and limitations under
|
||||
the License.
|
||||
|
||||
Copyright (C) 2011-2012 Jos de Jong, http://jsoneditoronline.org
|
||||
Copyright (C) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
|
||||
@author Jos de Jong, <wjosdejong@gmail.com>
|
||||
@date 2012-11-03
|
||||
@date 2013-01-01
|
||||
-->
|
||||
|
||||
<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.">
|
||||
|
@ -165,7 +165,7 @@
|
|||
•
|
||||
<a href="datapolicy.txt" target="_blank" class="footer">Data policy</a>
|
||||
•
|
||||
<a href="NOTICE" target="_blank" class="footer">Copyright 2011-2012 Jos de Jong</a>
|
||||
<a href="NOTICE" target="_blank" class="footer">Copyright 2011-2013 Jos de Jong</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -33,10 +33,10 @@
|
|||
License for the specific language governing permissions and limitations under
|
||||
the License.
|
||||
|
||||
Copyright (C) 2011-2012 Jos de Jong, http://jsoneditoronline.org
|
||||
Copyright (C) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
|
||||
@author Jos de Jong, <wjosdejong@gmail.com>
|
||||
@date 2012-11-03
|
||||
@date 2013-01-01
|
||||
-->
|
||||
|
||||
<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.">
|
||||
|
@ -47,12 +47,23 @@
|
|||
|
||||
<link href="app.css" rel="stylesheet" type="text/css">
|
||||
<link href="fileretriever.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../jsoneditor/jsoneditor.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../jsoneditor/css/jsoneditor.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../jsoneditor/css/menu.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../jsoneditor/css/searchbox.css" rel="stylesheet" type="text/css">
|
||||
<link href="../../jsoneditor/css/contextmenu.css" rel="stylesheet" type="text/css">
|
||||
<!-- TODO: droid font
|
||||
<link href='http://fonts.googleapis.com/css?family=Droid+Sans+Mono' rel='stylesheet' type='text/css'>
|
||||
-->
|
||||
|
||||
<script type="text/javascript" src="../../jsoneditor/jsoneditor.js"></script>
|
||||
<script type="text/javascript" src="../../jsoneditor/js/jsoneditor.js"></script>
|
||||
<script type="text/javascript" src="../../jsoneditor/js/jsonformatter.js"></script>
|
||||
<script type="text/javascript" src="../../jsoneditor/js/node.js"></script>
|
||||
<script type="text/javascript" src="../../jsoneditor/js/appendnode.js"></script>
|
||||
<script type="text/javascript" src="../../jsoneditor/js/contextmenu.js"></script>
|
||||
<script type="text/javascript" src="../../jsoneditor/js/history.js"></script>
|
||||
<script type="text/javascript" src="../../jsoneditor/js/searchbox.js"></script>
|
||||
<script type="text/javascript" src="../../jsoneditor/js/highlighter.js"></script>
|
||||
<script type="text/javascript" src="../../jsoneditor/js/util.js"></script>
|
||||
<script type="text/javascript" src="queryparams.js"></script>
|
||||
<script type="text/javascript" src="ajax.js"></script>
|
||||
<script type="text/javascript" src="fileretriever.js"></script>
|
||||
|
@ -63,10 +74,10 @@
|
|||
|
||||
<style type="text/css">
|
||||
div.convert-right {
|
||||
background: url('../../jsoneditor/img/jsoneditor-icons.png') -0 -48px;
|
||||
background: url('../../jsoneditor/css/img/jsoneditor-icons.png') -0 -48px;
|
||||
}
|
||||
div.convert-left {
|
||||
background: url('../../jsoneditor/img/jsoneditor-icons.png') -24px -48px;
|
||||
background: url('../../jsoneditor/css/img/jsoneditor-icons.png') -24px -48px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -191,7 +202,7 @@
|
|||
•
|
||||
<a href="datapolicy.txt" target="_blank" class="footer">Data policy</a>
|
||||
•
|
||||
<a href="../../NOTICE" target="_blank" class="footer">Copyright 2011-2012 Jos de Jong</a>
|
||||
<a href="../../NOTICE" target="_blank" class="footer">Copyright 2011-2013 Jos de Jong</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
80
build.xml
80
build.xml
|
@ -9,11 +9,14 @@
|
|||
<property name="compressor" value="tools/yuicompressor-2.4.7.jar" />
|
||||
|
||||
<!-- directories -->
|
||||
<property name="root" location="" />
|
||||
<property name="lib" location="build/lib" />
|
||||
<property name="web_app" location="build/app/web" />
|
||||
<property name="chrome_app" location="build/app/chrome" />
|
||||
<property name="web_app_src" location="app/web" />
|
||||
<property name="src" location="jsoneditor" />
|
||||
<property name="js_src" location="jsoneditor/js" />
|
||||
<property name="css_src" location="jsoneditor/css" />
|
||||
<property name="img_src" location="jsoneditor/css/img" />
|
||||
<property name="jsoneditor" location="${lib}/${package}-${version}" />
|
||||
<property name="jsoneditor_min" location="${lib}/${package}-${version}.min" />
|
||||
|
||||
|
@ -22,43 +25,72 @@
|
|||
<delete dir="${jsoneditor_min}" />
|
||||
|
||||
<!-- copy all files for the non-minified jsoneditor -->
|
||||
<copy file="${root}/LICENSE" todir="${jsoneditor}" />
|
||||
<copy file="${root}/NOTICE" todir="${jsoneditor}" />
|
||||
<copy file="${root}/README.md" todir="${jsoneditor}" />
|
||||
<copy file="${root}/changelog.txt" todir="${jsoneditor}" />
|
||||
<copy file="${root}/demo.html" todir="${jsoneditor}" />
|
||||
<copy file="${root}/jsoneditor/jsoneditor.js" todir="${jsoneditor}/jsoneditor" />
|
||||
<copy file="${root}/jsoneditor/jsoneditor.css" todir="${jsoneditor}/jsoneditor" />
|
||||
<copy file="${root}/jsoneditor/img/jsoneditor-icons.png" todir="${jsoneditor}/jsoneditor/img" />
|
||||
<copy file="README.md" todir="${jsoneditor}" />
|
||||
<copy file="LICENSE" todir="${jsoneditor}" />
|
||||
<copy file="NOTICE" todir="${jsoneditor}" />
|
||||
<copy file="changelog.txt" todir="${jsoneditor}" />
|
||||
<copy todir="${jsoneditor}/examples">
|
||||
<fileset dir="${src}/examples"/>
|
||||
</copy>
|
||||
<copy file="${img_src}/jsoneditor-icons.png" todir="${jsoneditor}/img" />
|
||||
|
||||
<!-- copy all files for the minified jsoneditor -->
|
||||
<copy file="${root}/LICENSE" todir="${jsoneditor_min}" />
|
||||
<copy file="${root}/NOTICE" todir="${jsoneditor_min}" />
|
||||
<copy file="${root}/README.md" todir="${jsoneditor_min}" />
|
||||
<copy file="${root}/changelog.txt" todir="${jsoneditor_min}" />
|
||||
<copy file="${root}/demo.html" todir="${jsoneditor_min}" />
|
||||
<copy file="${root}/jsoneditor/img/jsoneditor-icons.png" todir="${jsoneditor_min}/jsoneditor/img" />
|
||||
<copy file="README.md" todir="${jsoneditor_min}" />
|
||||
<copy file="LICENSE" todir="${jsoneditor_min}" />
|
||||
<copy file="NOTICE" todir="${jsoneditor_min}" />
|
||||
<copy file="changelog.txt" todir="${jsoneditor_min}" />
|
||||
<copy todir="${jsoneditor_min}/examples">
|
||||
<fileset dir="${src}/examples"/>
|
||||
</copy>
|
||||
<replace dir="${jsoneditor_min}/examples" value="jsoneditor-min.js">
|
||||
<include name="**/*.html"/>
|
||||
<replacetoken>jsoneditor.js</replacetoken>
|
||||
</replace>
|
||||
<replace dir="${jsoneditor_min}/examples" value="jsoneditor-min.css">
|
||||
<include name="**/*.html"/>
|
||||
<replacetoken>jsoneditor.css</replacetoken>
|
||||
</replace>
|
||||
<copy file="${img_src}/jsoneditor-icons.png" todir="${jsoneditor_min}/img" />
|
||||
|
||||
<!-- concatenate the javascript and css app files -->
|
||||
<concat destfile="${jsoneditor}/jsoneditor.js">
|
||||
<fileset dir="${js_src}" includes="jsoneditor.js"/>
|
||||
<fileset dir="${js_src}" includes="jsonformatter.js"/>
|
||||
<fileset dir="${js_src}" includes="node.js"/>
|
||||
<fileset dir="${js_src}" includes="appendnode.js"/>
|
||||
<fileset dir="${js_src}" includes="contextmenu.js"/>
|
||||
<fileset dir="${js_src}" includes="history.js"/>
|
||||
<fileset dir="${js_src}" includes="searchbox.js"/>
|
||||
<fileset dir="${js_src}" includes="highlighter.js"/>
|
||||
<fileset dir="${js_src}" includes="util.js"/>
|
||||
</concat>
|
||||
<concat destfile="${jsoneditor}/jsoneditor.css">
|
||||
<fileset dir="${css_src}" includes="jsoneditor.css"/>
|
||||
<fileset dir="${css_src}" includes="menu.css"/>
|
||||
<fileset dir="${css_src}" includes="contextmenu.css"/>
|
||||
<fileset dir="${css_src}" includes="searchbox.css"/>
|
||||
</concat>
|
||||
|
||||
<!-- minify the jsoneditor files -->
|
||||
<java jar="${compressor}" dir="jsoneditor" fork="true" failonerror="true">
|
||||
<java jar="${compressor}" dir="${jsoneditor}/" fork="true" failonerror="true">
|
||||
<arg value="-o"/>
|
||||
<arg value="${jsoneditor_min}/jsoneditor/jsoneditor-min.js"/>
|
||||
<arg value="${jsoneditor_min}/jsoneditor-min.js"/>
|
||||
<arg value="jsoneditor.js"/>
|
||||
</java>
|
||||
<java jar="${compressor}" dir="jsoneditor" fork="true" failonerror="true">
|
||||
<java jar="${compressor}" dir="${jsoneditor}" fork="true" failonerror="true">
|
||||
<arg value="-o"/>
|
||||
<arg value="${jsoneditor_min}/jsoneditor/jsoneditor-min.css"/>
|
||||
<arg value="${jsoneditor_min}/jsoneditor-min.css"/>
|
||||
<arg value="jsoneditor.css"/>
|
||||
</java>
|
||||
|
||||
<!-- create a zip file with non-minified jsoneditor -->
|
||||
<zip destfile="${lib}/${package}-${version}.zip">
|
||||
<fileset dir="${jsoneditor}" includes="**" />
|
||||
<fileset dir="${lib}" includes="${package}-${version}/*" />
|
||||
</zip>
|
||||
|
||||
<!-- create a zip file with minified jsoneditor -->
|
||||
<zip destfile="${lib}/${package}-${version}.min.zip">
|
||||
<fileset dir="${jsoneditor_min}" includes="**" />
|
||||
<fileset dir="${lib}" includes="${package}-${version}.min/*" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
|
@ -94,9 +126,9 @@
|
|||
<copy file="${web_app_src}/img/header_background.png" todir="${web_app}/img" />
|
||||
|
||||
<copy file="${web_app_src}/lib/jsonlint/jsonlint.js" todir="${web_app}/lib/jsonlint" />
|
||||
<copy file="${jsoneditor_min}/jsoneditor/jsoneditor-min.js" todir="${web_app}/lib/jsoneditor" />
|
||||
<copy file="${jsoneditor_min}/jsoneditor/jsoneditor-min.css" todir="${web_app}/lib/jsoneditor" />
|
||||
<copy file="${jsoneditor_min}/jsoneditor/img/jsoneditor-icons.png" todir="${web_app}/lib/jsoneditor/img" />
|
||||
<copy file="${jsoneditor_min}/jsoneditor-min.js" todir="${web_app}/lib/jsoneditor" />
|
||||
<copy file="${jsoneditor_min}/jsoneditor-min.css" todir="${web_app}/lib/jsoneditor" />
|
||||
<copy file="${jsoneditor_min}/img/jsoneditor-icons.png" todir="${web_app}/lib/jsoneditor/img" />
|
||||
|
||||
<!-- minify the javascript files -->
|
||||
<java jar="${compressor}" dir="${web_app}" fork="true" failonerror="true">
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
|
||||
/* _______________________________ MAIN MENU ________________________________ */
|
||||
|
||||
div.jsoneditor-contextmenu {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul {
|
||||
position: relative;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 124px;
|
||||
|
||||
background: white;
|
||||
border: 1px solid #d3d3d3;
|
||||
box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
|
||||
|
||||
z-index: 1;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 124px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: #4d4d4d;
|
||||
background: transparent;
|
||||
|
||||
line-height: 24px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Fix button padding in firefox */
|
||||
div.jsoneditor-contextmenu ul li button::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button:hover {
|
||||
color: #1a1a1a;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button.default {
|
||||
width: 92px;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button.expand {
|
||||
float: right;
|
||||
width: 32px;
|
||||
height: 24px;
|
||||
border-left: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu div.icon {
|
||||
float: left;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-image: url('img/jsoneditor-icons.png');
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button div.expand {
|
||||
float: right;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0 4px 0 0;
|
||||
background: url('img/jsoneditor-icons.png') 0 -72px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button:hover div.expand,
|
||||
div.jsoneditor-contextmenu ul li.selected div.expand,
|
||||
div.jsoneditor-contextmenu ul li button.expand:hover div.expand {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu .separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
padding-top: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
button.jsoneditor-remove > .icon {
|
||||
background-position: -24px -24px;
|
||||
}
|
||||
button.jsoneditor-remove:hover > .icon {
|
||||
background-position: -24px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-append > .icon {
|
||||
background-position: 0 -24px;
|
||||
}
|
||||
button.jsoneditor-append:hover > .icon {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-insert > .icon {
|
||||
background-position: 0 -24px;
|
||||
}
|
||||
button.jsoneditor-insert:hover > .icon {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-insert-above > .icon {
|
||||
background-position: -24px -24px;
|
||||
}
|
||||
button.jsoneditor-insert-above:hover > .icon {
|
||||
background-position: -24px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-insert-below > .icon {
|
||||
background-position: -48px -24px;
|
||||
}
|
||||
button.jsoneditor-insert-below:hover > .icon {
|
||||
background-position: -48px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-duplicate > .icon {
|
||||
background-position: -48px -24px;
|
||||
}
|
||||
button.jsoneditor-duplicate:hover > .icon {
|
||||
background-position: -48px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-sort-asc > .icon {
|
||||
background-position: -168px -24px;
|
||||
}
|
||||
button.jsoneditor-sort-asc:hover > .icon {
|
||||
background-position: -168px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-sort-desc > .icon {
|
||||
background-position: -192px -24px;
|
||||
}
|
||||
button.jsoneditor-sort-desc:hover > .icon {
|
||||
background-position: -192px 0;
|
||||
}
|
||||
|
||||
/* ____________________________ CONTEXT SUB MENU ____________________________ */
|
||||
|
||||
|
||||
div.jsoneditor-contextmenu ul li ul li .selected {
|
||||
background-color: #D5DDF6;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li ul {
|
||||
display: none;
|
||||
position: relative;
|
||||
left: -10px;
|
||||
top: 0;
|
||||
|
||||
border: none;
|
||||
box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5);
|
||||
padding: 0 10px;
|
||||
|
||||
/* TODO: transition is not supported on IE8-9 */
|
||||
-webkit-transition: all 0.3s ease-out;
|
||||
-moz-transition: all 0.3s ease-out;
|
||||
-o-transition: all 0.3s ease-out;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li.selected ul {
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li ul li button {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li ul li button:hover {
|
||||
background-color: #f5f5f5;
|
||||
|
||||
}
|
||||
|
||||
button.jsoneditor-type-string > .icon {
|
||||
background-position: -144px -24px;
|
||||
}
|
||||
button.jsoneditor-type-string:hover > .icon,
|
||||
button.jsoneditor-type-string.selected > .icon{
|
||||
background-position: -144px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-type-auto > .icon {
|
||||
background-position: -120px -24px;
|
||||
}
|
||||
button.jsoneditor-type-auto:hover > .icon,
|
||||
button.jsoneditor-type-auto.selected > .icon {
|
||||
background-position: -120px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-type-object > .icon {
|
||||
background-position: -72px -24px;
|
||||
}
|
||||
button.jsoneditor-type-object:hover > .icon,
|
||||
button.jsoneditor-type-object.selected > .icon{
|
||||
background-position: -72px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-type-array > .icon {
|
||||
background-position: -96px -24px;
|
||||
}
|
||||
button.jsoneditor-type-array:hover > .icon,
|
||||
button.jsoneditor-type-array.selected > .icon{
|
||||
background-position: -96px 0;
|
||||
}
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
@ -0,0 +1,235 @@
|
|||
|
||||
.jsoneditor-field, .jsoneditor-value, .jsoneditor-field-readonly, .jsoneditor-readonly {
|
||||
border: 1px solid transparent;
|
||||
min-height: 16px;
|
||||
min-width: 24px;
|
||||
padding: 2px;
|
||||
margin: 1px;
|
||||
outline: none;
|
||||
word-wrap: break-word;
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* adjust margin of p elements inside editable divs, needed for Opera, IE */
|
||||
.jsoneditor-field p, .jsoneditor-value p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.jsoneditor-value {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.jsoneditor-empty {
|
||||
background-color: #E5E5E5;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsoneditor-separator {
|
||||
padding: 3px 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.jsoneditor-value:focus, .jsoneditor-field:focus,
|
||||
.jsoneditor-value:hover, .jsoneditor-field:hover,
|
||||
.jsoneditor-search-highlight {
|
||||
background-color: #FFFFAB;
|
||||
border: 1px solid yellow;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsoneditor-search-highlight-active,
|
||||
.jsoneditor-search-highlight-active:focus,
|
||||
.jsoneditor-search-highlight-active:hover {
|
||||
background-color: #ffee00;
|
||||
border: 1px solid #ffc700;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsoneditor-field-readonly:hover {
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.jsoneditor-readonly {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
button.jsoneditor-collapsed, button.jsoneditor-expanded,
|
||||
button.jsoneditor-invisible, button.jsoneditor-dragarea,
|
||||
button.jsoneditor-contextmenu, button.jsoneditor-append {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
background-image: url('img/jsoneditor-icons.png');
|
||||
}
|
||||
|
||||
/* TODO: no global settings
|
||||
button:disabled {
|
||||
color: #808080;
|
||||
}
|
||||
*/
|
||||
|
||||
td.jsoneditor-nochilds {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
button.jsoneditor-collapsed {
|
||||
background-position: 0 -48px;
|
||||
}
|
||||
|
||||
button.jsoneditor-expanded {
|
||||
background-position: 0 -72px;
|
||||
}
|
||||
|
||||
.jsoneditor-contextmenu {
|
||||
position: relative;
|
||||
background-position: -48px -72px;
|
||||
}
|
||||
|
||||
.jsoneditor-contextmenu:hover, .jsoneditor-contextmenu:focus {
|
||||
background-position: -48px -48px;
|
||||
}
|
||||
|
||||
button.jsoneditor-invisible {
|
||||
visibility: hidden;
|
||||
background: none;
|
||||
}
|
||||
|
||||
button.jsoneditor-collapsed, button.jsoneditor-expanded,
|
||||
button.jsoneditor-invisible {
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.jsoneditor-frame {
|
||||
color: #1A1A1A;
|
||||
border: 1px solid #97B0F8;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.jsoneditor-table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.jsoneditor-content-outer, div.jsonformatter-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: -35px 0 0 0;
|
||||
padding: 35px 0 0 0;
|
||||
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.jsoneditor-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
textarea.jsonformatter-textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
border: none;
|
||||
background-color: white;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
tr.jsoneditor-tr-highlight {
|
||||
background-color: #FFFFAB;
|
||||
}
|
||||
|
||||
button.jsoneditor-dragarea {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
/*
|
||||
margin: 3px 0;
|
||||
background: url('img/dots_gray.gif') top center;
|
||||
background-repeat: repeat-y;
|
||||
*/
|
||||
background: url('img/jsoneditor-icons.png') -72px -72px;
|
||||
|
||||
display: block;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
button.jsoneditor-dragarea:hover, .jsoneditor-dragarea:focus {
|
||||
background-position: -72px -48px;
|
||||
}
|
||||
|
||||
/* TODO: do not change global tr, th, td */
|
||||
tr, th, td {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
td.jsoneditor-td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td.jsoneditor-td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
td.jsoneditor-td-edit {
|
||||
background-color: #F5F5F5;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
td.jsoneditor-td-tree {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td.jsoneditor-droparea {
|
||||
height: 24px;
|
||||
|
||||
border-top: 1px dashed gray;
|
||||
border-bottom: 1px dashed gray;
|
||||
background-color: #FFFF80;
|
||||
}
|
||||
|
||||
.jsoneditor-field, .jsoneditor-value, .jsoneditor-td, .jsoneditor-th,
|
||||
.jsoneditor-type, .jsonformatter-textarea {
|
||||
font-family: droid sans mono, monospace, courier new, courier, sans-serif;
|
||||
font-size: 10pt;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu button,
|
||||
input.jsoneditor-search, div.jsoneditor-search-results {
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.jsoneditor-hidden-focus {
|
||||
position: absolute;
|
||||
left: -1000px;
|
||||
top: -1000px;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* TODO: drastically cleanup the css, improve/simplify naming and cascading */
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
/* __________________________ JSONEDITOR TOP MENU ___________________________ */
|
||||
|
||||
|
||||
div.jsoneditor-menu {
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
color: #1A1A1A;
|
||||
background-color: #D5DDF6;
|
||||
border-bottom: 1px solid #97B0F8;
|
||||
}
|
||||
|
||||
button.jsoneditor-menu {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #aec0f8;
|
||||
background: #e3eaf6 url('img/jsoneditor-icons.png');
|
||||
}
|
||||
|
||||
button.jsoneditor-menu:hover {
|
||||
background-color: #f0f2f5;
|
||||
}
|
||||
button.jsoneditor-menu:active {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
button.jsoneditor-menu:disabled {
|
||||
background-color: #e3eaf6;
|
||||
}
|
||||
|
||||
button.jsoneditor-collapse-all {
|
||||
background-position: 0 -96px;
|
||||
}
|
||||
button.jsoneditor-expand-all {
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
button.jsoneditor-undo {
|
||||
background-position: -24px -96px;
|
||||
}
|
||||
button.jsoneditor-undo:disabled {
|
||||
background-position: -24px -120px;
|
||||
}
|
||||
button.jsoneditor-redo {
|
||||
background-position: -48px -96px;
|
||||
}
|
||||
button.jsoneditor-redo:disabled {
|
||||
background-position: -48px -120px;
|
||||
}
|
||||
/* TODO: css for button:disabled is not supported by IE8 */
|
||||
button.jsoneditor-compact {
|
||||
background-position: -72px -96px;
|
||||
}
|
||||
button.jsoneditor-format {
|
||||
background-position: -72px -120px;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
table.jsoneditor-search {
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
table.jsoneditor-search-input {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
div.jsoneditor-search {
|
||||
border: 1px solid #97B0F8;
|
||||
background-color: white;
|
||||
padding: 0 2px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input.jsoneditor-search {
|
||||
width: 120px;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
div.jsoneditor-search-results {
|
||||
color: #4d4d4d;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
button.jsoneditor-search-refresh, button.jsoneditor-search-next,
|
||||
button.jsoneditor-search-previous {
|
||||
width: 16px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: url('img/jsoneditor-icons.png');
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
button.jsoneditor-search-refresh {
|
||||
width: 18px;
|
||||
background-position: -99px -73px;
|
||||
}
|
||||
|
||||
button.jsoneditor-search-next {
|
||||
cursor: pointer;
|
||||
background-position: -124px -73px;
|
||||
}
|
||||
button.jsoneditor-search-next:hover {
|
||||
background-position: -124px -49px;
|
||||
}
|
||||
|
||||
button.jsoneditor-search-previous {
|
||||
cursor: pointer;
|
||||
background-position: -148px -73px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
button.jsoneditor-search-previous:hover {
|
||||
background-position: -148px -49px;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="jsoneditor/jsoneditor.css">
|
||||
<script type="text/javascript" src="jsoneditor/jsoneditor.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../jsoneditor.css">
|
||||
<script type="text/javascript" src="../jsoneditor.js"></script>
|
||||
<style type="text/css">
|
||||
body {font: 11pt sans-serif;}
|
||||
</style>
|
|
@ -0,0 +1,224 @@
|
|||
/**
|
||||
* @license
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @constructor JSONEditor.AppendNode
|
||||
* @extends JSONEditor.Node
|
||||
* @param {JSONEditor} editor
|
||||
* Create a new AppendNode. This is a special node which is created at the
|
||||
* end of the list with childs for an object or array
|
||||
*/
|
||||
JSONEditor.AppendNode = function (editor) {
|
||||
this.editor = editor;
|
||||
this.dom = {};
|
||||
};
|
||||
|
||||
JSONEditor.AppendNode.prototype = new JSONEditor.Node();
|
||||
|
||||
/**
|
||||
* Return a table row with an append button.
|
||||
* @return {Element} dom TR element
|
||||
*/
|
||||
JSONEditor.AppendNode.prototype.getDom = function () {
|
||||
// TODO: do not create the DOM for the appendNode when in viewer mode
|
||||
// TODO: implement a new solution for the append node
|
||||
var dom = this.dom;
|
||||
|
||||
if (dom.tr) {
|
||||
return dom.tr;
|
||||
}
|
||||
|
||||
// a row for the append button
|
||||
var trAppend = document.createElement('tr');
|
||||
trAppend.node = this;
|
||||
dom.tr = trAppend;
|
||||
|
||||
// when in viewer mode, don't create the contents for the append node
|
||||
// but return here.
|
||||
if (!this.editor.editable) {
|
||||
return trAppend;
|
||||
}
|
||||
|
||||
// TODO: consistent naming
|
||||
|
||||
// a cell for the dragarea column
|
||||
var tdDrag = document.createElement('td');
|
||||
tdDrag.className = 'jsoneditor-td';
|
||||
dom.tdDrag = tdDrag;
|
||||
|
||||
// create context menu
|
||||
var tdMenu = document.createElement('td');
|
||||
tdMenu.className = 'jsoneditor-td';
|
||||
var menu = document.createElement('button');
|
||||
menu.className = 'jsoneditor-contextmenu';
|
||||
dom.menu = menu;
|
||||
dom.tdMenu = tdMenu;
|
||||
tdMenu.appendChild(dom.menu);
|
||||
|
||||
// a cell for the contents (showing text 'empty')
|
||||
var tdAppend = document.createElement('td');
|
||||
var domText = document.createElement('div');
|
||||
domText.innerHTML = '(empty)';
|
||||
domText.className = 'jsoneditor-readonly';
|
||||
tdAppend.appendChild(domText);
|
||||
tdAppend.className = 'jsoneditor-td';
|
||||
dom.td = tdAppend;
|
||||
dom.text = domText;
|
||||
|
||||
this.updateDom();
|
||||
|
||||
return trAppend;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the HTML dom of the Node
|
||||
*/
|
||||
JSONEditor.AppendNode.prototype.updateDom = function () {
|
||||
var dom = this.dom;
|
||||
var tdAppend = dom.td;
|
||||
if (tdAppend) {
|
||||
tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px';
|
||||
// TODO: not so nice hard coded offset
|
||||
}
|
||||
|
||||
var domText = dom.text;
|
||||
if (domText) {
|
||||
domText.innerHTML = '(empty ' + this.parent.type + ')';
|
||||
}
|
||||
|
||||
// attach or detach the contents of the append node:
|
||||
// hide when the parent has childs, show when the parent has no childs
|
||||
var trAppend = dom.tr;
|
||||
if (!this.isVisible()) {
|
||||
if (dom.tr.firstChild) {
|
||||
trAppend.removeChild(dom.tdDrag);
|
||||
trAppend.removeChild(dom.tdMenu);
|
||||
trAppend.removeChild(tdAppend);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!dom.tr.firstChild) {
|
||||
trAppend.appendChild(dom.tdDrag);
|
||||
trAppend.appendChild(dom.tdMenu);
|
||||
trAppend.appendChild(tdAppend);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether the AppendNode is currently visible.
|
||||
* the AppendNode is visible when its parent has no childs (i.e. is empty).
|
||||
* @return {boolean} isVisible
|
||||
*/
|
||||
JSONEditor.AppendNode.prototype.isVisible = function () {
|
||||
return (this.parent.childs.length == 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Show a contextmenu for this node
|
||||
* @param {function} [onClose] Callback method called when the context menu
|
||||
* is being closed.
|
||||
*/
|
||||
JSONEditor.AppendNode.prototype.showContextMenu = function (onClose) {
|
||||
var node = this;
|
||||
var titles = JSONEditor.Node.TYPE_TITLES;
|
||||
var items = [
|
||||
// create append button
|
||||
{
|
||||
'text': 'Append',
|
||||
'title': 'Append a new node with type \'auto\'',
|
||||
'submenuTitle': 'Select the type of the node to be appended',
|
||||
'className': 'jsoneditor-insert',
|
||||
'click': function () {
|
||||
node._onAppend('field', 'value', 'auto');
|
||||
},
|
||||
'submenu': [
|
||||
{
|
||||
'text': 'Auto',
|
||||
'className': 'jsoneditor-type-auto',
|
||||
'title': titles.auto,
|
||||
'click': function () {
|
||||
node._onAppend('field', 'value', 'auto');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Array',
|
||||
'className': 'jsoneditor-type-array',
|
||||
'title': titles.array,
|
||||
'click': function () {
|
||||
node._onAppend('field', []);
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Object',
|
||||
'className': 'jsoneditor-type-object',
|
||||
'title': titles.object,
|
||||
'click': function () {
|
||||
node._onAppend('field', {});
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'String',
|
||||
'className': 'jsoneditor-type-string',
|
||||
'title': titles.string,
|
||||
'click': function () {
|
||||
// TODO: settings type string does not work, will become auto
|
||||
node._onAppend('field', 'value', 'string');
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
var menu = new JSONEditor.ContextMenu(items, {close: onClose});
|
||||
menu.show(this.dom.menu);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle an event. The event is catched centrally by the editor
|
||||
* @param {Event} event
|
||||
*/
|
||||
JSONEditor.AppendNode.prototype.onEvent = function (event) {
|
||||
var type = event.type;
|
||||
var target = event.target || event.srcElement;
|
||||
var dom = this.dom;
|
||||
|
||||
// highlight the append nodes parent
|
||||
var menu = dom.menu;
|
||||
if (target == menu) {
|
||||
if (type == 'mouseover') {
|
||||
this.editor.highlighter.highlight(this.parent);
|
||||
}
|
||||
else if (type == 'mouseout') {
|
||||
this.editor.highlighter.unhighlight();
|
||||
}
|
||||
}
|
||||
|
||||
// context menu events
|
||||
if (type == 'click' && target == dom.menu) {
|
||||
var highlighter = this.editor.highlighter;
|
||||
highlighter.highlight(this.parent);
|
||||
highlighter.lock();
|
||||
this.showContextMenu(function () {
|
||||
highlighter.unlock();
|
||||
highlighter.unhighlight();
|
||||
});
|
||||
}
|
||||
};
|
|
@ -0,0 +1,272 @@
|
|||
/**
|
||||
* @license
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* A context menu
|
||||
* @param {Object[]} items Array containing the menu structure
|
||||
* TODO: describe structure
|
||||
* @param {Object} [options] Object with options. Available options:
|
||||
* {function} close Callback called when the
|
||||
* context menu is being closed.
|
||||
* @constructor
|
||||
*/
|
||||
JSONEditor.ContextMenu = function (items, options) {
|
||||
var me = this;
|
||||
this.items = items;
|
||||
this.eventListeners = {};
|
||||
this.visibleSubmenu = undefined;
|
||||
this.onClose = options ? options.close : undefined;
|
||||
|
||||
// create a container element
|
||||
var menu = document.createElement('div');
|
||||
menu.className = 'jsoneditor-contextmenu';
|
||||
this.menu = menu;
|
||||
|
||||
// create a list to hold the menu items
|
||||
var list = document.createElement('ul');
|
||||
list.className = 'menu';
|
||||
menu.appendChild(list);
|
||||
this.list = list;
|
||||
|
||||
function createMenuItems (list, items) {
|
||||
items.forEach(function (item) {
|
||||
if (item.type == 'separator') {
|
||||
// create a separator
|
||||
var separator = document.createElement('div');
|
||||
separator.className = 'separator';
|
||||
li = document.createElement('li');
|
||||
li.appendChild(separator);
|
||||
list.appendChild(li);
|
||||
}
|
||||
else {
|
||||
// create a menu item
|
||||
var li = document.createElement('li');
|
||||
list.appendChild(li);
|
||||
|
||||
// create a button in the menu item
|
||||
var button = document.createElement('button');
|
||||
button.className = item.className;
|
||||
if (item.title) {
|
||||
button.title = item.title;
|
||||
}
|
||||
if (item.click) {
|
||||
button.onclick = function () {
|
||||
me.hide();
|
||||
item.click();
|
||||
};
|
||||
}
|
||||
li.appendChild(button);
|
||||
|
||||
// create the contents of the button
|
||||
if (item.submenu) {
|
||||
// add the icon to the button
|
||||
var divIcon = document.createElement('div');
|
||||
divIcon.className = 'icon';
|
||||
button.appendChild(divIcon);
|
||||
button.appendChild(document.createTextNode(item.text));
|
||||
|
||||
var buttonSubmenu;
|
||||
if (item.click) {
|
||||
// submenu and a button with a click handler
|
||||
button.className += ' default';
|
||||
|
||||
var buttonExpand = document.createElement('button');
|
||||
buttonExpand.className = 'expand';
|
||||
buttonExpand.innerHTML = '<div class="expand"></div>';
|
||||
li.appendChild(buttonExpand);
|
||||
if (item.submenuTitle) {
|
||||
buttonExpand.title = item.submenuTitle;
|
||||
}
|
||||
|
||||
buttonSubmenu = buttonExpand;
|
||||
}
|
||||
else {
|
||||
// submenu and a button without a click handler
|
||||
var divExpand = document.createElement('div');
|
||||
divExpand.className = 'expand';
|
||||
button.appendChild(divExpand);
|
||||
|
||||
buttonSubmenu = button;
|
||||
}
|
||||
|
||||
// attach a handler to expand/collapse the submenu
|
||||
var selected = false;
|
||||
buttonSubmenu.onclick = function () {
|
||||
me._onShowSubmenu(submenu);
|
||||
};
|
||||
|
||||
// create the submenu
|
||||
var submenu = document.createElement('ul');
|
||||
submenu.className = 'menu';
|
||||
submenu.style.height = '0';
|
||||
li.appendChild(submenu);
|
||||
createMenuItems(submenu, item.submenu);
|
||||
}
|
||||
else {
|
||||
// no submenu, just a button with clickhandler
|
||||
button.innerHTML = '<div class="icon"></div>' + item.text;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
createMenuItems(list, items);
|
||||
|
||||
// TODO: when the editor is small, show the submenu on the right instead of inline?
|
||||
|
||||
// calculate the max height of the menu with one submenu expanded
|
||||
this.maxHeight = 0; // height in pixels
|
||||
items.forEach(function (item) {
|
||||
var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24;
|
||||
me.maxHeight = Math.max(me.maxHeight, height);
|
||||
});
|
||||
};
|
||||
|
||||
// currently displayed context menu, a singleton. We may only have one visible context menu
|
||||
JSONEditor.ContextMenu.visibleMenu = undefined;
|
||||
|
||||
/**
|
||||
* Attach the menu to an anchor
|
||||
* @param {Element} anchor
|
||||
*/
|
||||
JSONEditor.ContextMenu.prototype.show = function (anchor) {
|
||||
this.hide();
|
||||
|
||||
// calculate whether the menu fits below the anchor
|
||||
var windowHeight = JSONEditor.util.getWindowHeight();
|
||||
var anchorHeight = anchor.offsetHeight;
|
||||
var menuHeight = this.maxHeight;
|
||||
|
||||
// position the menu
|
||||
var left = JSONEditor.util.getAbsoluteLeft(anchor);
|
||||
var top = JSONEditor.util.getAbsoluteTop(anchor);
|
||||
if (top + anchorHeight + menuHeight < windowHeight) {
|
||||
// display the menu below the anchor
|
||||
this.menu.style.left = left + 'px';
|
||||
this.menu.style.top = (top + anchorHeight) + 'px';
|
||||
this.menu.style.bottom = '';
|
||||
}
|
||||
else {
|
||||
// display the menu above the anchor
|
||||
this.menu.style.left = left + 'px';
|
||||
this.menu.style.top = '';
|
||||
this.menu.style.bottom = (windowHeight - top) + 'px';
|
||||
}
|
||||
|
||||
// attach the menu to the document
|
||||
document.body.appendChild(this.menu);
|
||||
|
||||
// create and attach event listeners
|
||||
var me = this;
|
||||
var list = this.list;
|
||||
this.eventListeners.mousedown = JSONEditor.util.addEventListener(
|
||||
document, 'mousedown', function (event) {
|
||||
// hide menu on click outside of the menu
|
||||
event = event || window.event;
|
||||
var target = event.target || event.srcElement;
|
||||
if (!JSONEditor.isChildOf(target, list)) {
|
||||
me.hide();
|
||||
}
|
||||
});
|
||||
this.eventListeners.mousewheel = JSONEditor.util.addEventListener(
|
||||
document, 'mousewheel', function () {
|
||||
// hide the menu on mouse scroll
|
||||
me.hide();
|
||||
});
|
||||
this.eventListeners.keydown = JSONEditor.util.addEventListener(
|
||||
document, 'keydown', function (event) {
|
||||
// hide the menu on ESC key
|
||||
event = event || window.event;
|
||||
var keynum = event.which || event.keyCode;
|
||||
if (keynum == 27) { // ESC
|
||||
me.hide();
|
||||
JSONEditor.util.stopPropagation(event);
|
||||
JSONEditor.util.preventDefault(event);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: focus to the first button in the context menu
|
||||
|
||||
if (JSONEditor.ContextMenu.visibleMenu) {
|
||||
JSONEditor.ContextMenu.visibleMenu.hide();
|
||||
}
|
||||
JSONEditor.ContextMenu.visibleMenu = this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the context menu if visible
|
||||
*/
|
||||
JSONEditor.ContextMenu.prototype.hide = function () {
|
||||
// remove the menu from the DOM
|
||||
if (this.menu.parentNode) {
|
||||
this.menu.parentNode.removeChild(this.menu);
|
||||
if (this.onClose) {
|
||||
this.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
// remove all event listeners
|
||||
// all event listeners are supposed to be attached to document.
|
||||
for (var name in this.eventListeners) {
|
||||
if (this.eventListeners.hasOwnProperty(name)) {
|
||||
var fn = this.eventListeners[name];
|
||||
if (fn) {
|
||||
JSONEditor.util.removeEventListener(document, name, fn);
|
||||
}
|
||||
delete this.eventListeners[name];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Show or hide a submenu.
|
||||
* Any currently visible submenu will be hided.
|
||||
* @param {Element} submenu
|
||||
* @private
|
||||
*/
|
||||
JSONEditor.ContextMenu.prototype._onShowSubmenu = function (submenu) {
|
||||
var me = this;
|
||||
var alreadyVisible = (submenu == this.visibleSubmenu);
|
||||
|
||||
// hide the currently visible submenu
|
||||
var visibleSubmenu = this.visibleSubmenu;
|
||||
if (visibleSubmenu) {
|
||||
visibleSubmenu.style.height = '0';
|
||||
visibleSubmenu.style.padding = '';
|
||||
setTimeout(function () {
|
||||
if (me.visibleSubmenu != visibleSubmenu) {
|
||||
visibleSubmenu.style.display = '';
|
||||
JSONEditor.util.removeClassName(visibleSubmenu.parentNode, 'selected');
|
||||
}
|
||||
}, 300); // timeout duration must match the css transition duration
|
||||
this.visibleSubmenu = undefined;
|
||||
}
|
||||
|
||||
if (!alreadyVisible) {
|
||||
submenu.style.display = 'block';
|
||||
var height = submenu.clientHeight; // force a reflow in Firefox
|
||||
setTimeout(function () {
|
||||
if (me.visibleSubmenu == submenu) {
|
||||
submenu.style.height = (submenu.childNodes.length * 24) + 'px';
|
||||
submenu.style.padding = '5px 10px';
|
||||
}
|
||||
}, 0);
|
||||
JSONEditor.util.addClassName(submenu.parentNode, 'selected');
|
||||
this.visibleSubmenu = submenu;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* @license
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The highlighter can highlight/unhighlight a node, and
|
||||
* animate the visibility of a context menu.
|
||||
* @constructor JSONEditor.Highlighter
|
||||
*/
|
||||
JSONEditor.Highlighter = function () {
|
||||
this.locked = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hightlight given node and its childs
|
||||
* @param {JSONEditor.Node} node
|
||||
*/
|
||||
JSONEditor.Highlighter.prototype.highlight = function (node) {
|
||||
if (this.locked) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.node != node) {
|
||||
// unhighlight current node
|
||||
if (this.node) {
|
||||
this.node.setHighlight(false);
|
||||
}
|
||||
|
||||
// highlight new node
|
||||
this.node = node;
|
||||
this.node.setHighlight(true);
|
||||
}
|
||||
|
||||
// cancel any current timeout
|
||||
this._cancelUnhighlight();
|
||||
};
|
||||
|
||||
/**
|
||||
* Unhighlight currently highlighted node.
|
||||
* Will be done after a delay
|
||||
*/
|
||||
JSONEditor.Highlighter.prototype.unhighlight = function () {
|
||||
if (this.locked) {
|
||||
return;
|
||||
}
|
||||
|
||||
var me = this;
|
||||
if (this.node) {
|
||||
this._cancelUnhighlight();
|
||||
|
||||
// do the unhighlighting after a small delay, to prevent re-highlighting
|
||||
// the same node when moving from the drag-icon to the contextmenu-icon
|
||||
// or vice versa.
|
||||
this.unhighlightTimer = setTimeout(function () {
|
||||
me.node.setHighlight(false);
|
||||
me.node = undefined;
|
||||
me.unhighlightTimer = undefined;
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel an unhighlight action (if before the timeout of the unhighlight action)
|
||||
* @private
|
||||
*/
|
||||
JSONEditor.Highlighter.prototype._cancelUnhighlight = function () {
|
||||
if (this.unhighlightTimer) {
|
||||
clearTimeout(this.unhighlightTimer);
|
||||
this.unhighlightTimer = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Lock highlighting or unhighlighting nodes.
|
||||
* methods highlight and unhighlight do not work while locked.
|
||||
*/
|
||||
JSONEditor.Highlighter.prototype.lock = function () {
|
||||
this.locked = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Unlock highlighting or unhighlighting nodes
|
||||
*/
|
||||
JSONEditor.Highlighter.prototype.unlock = function () {
|
||||
this.locked = false;
|
||||
};
|
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
* @license
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @constructor JSONEditor.History
|
||||
* Store action history, enables undo and redo
|
||||
* @param {JSONEditor} editor
|
||||
*/
|
||||
JSONEditor.History = function (editor) {
|
||||
this.editor = editor;
|
||||
this.clear();
|
||||
|
||||
// map with all supported actions
|
||||
this.actions = {
|
||||
'editField': {
|
||||
'undo': function (obj) {
|
||||
obj.params.node.updateField(obj.params.oldValue);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.node.updateField(obj.params.newValue);
|
||||
}
|
||||
},
|
||||
'editValue': {
|
||||
'undo': function (obj) {
|
||||
obj.params.node.updateValue(obj.params.oldValue);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.node.updateValue(obj.params.newValue);
|
||||
}
|
||||
},
|
||||
'appendNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.node);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.appendChild(obj.params.node);
|
||||
}
|
||||
},
|
||||
'insertBeforeNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.node);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.insertBefore(obj.params.node, obj.params.beforeNode);
|
||||
}
|
||||
},
|
||||
'insertAfterNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.node);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.insertAfter(obj.params.node, obj.params.afterNode);
|
||||
}
|
||||
},
|
||||
'removeNode': {
|
||||
'undo': function (obj) {
|
||||
var parent = obj.params.parent;
|
||||
var beforeNode = parent.childs[obj.params.index] || parent.append;
|
||||
parent.insertBefore(obj.params.node, beforeNode);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.node);
|
||||
}
|
||||
},
|
||||
'duplicateNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.clone);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.insertAfter(obj.params.clone, obj.params.node);
|
||||
}
|
||||
},
|
||||
'changeType': {
|
||||
'undo': function (obj) {
|
||||
obj.params.node.changeType(obj.params.oldType);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.node.changeType(obj.params.newType);
|
||||
}
|
||||
},
|
||||
'moveNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.startParent.moveTo(obj.params.node, obj.params.startIndex);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.endParent.moveTo(obj.params.node, obj.params.endIndex);
|
||||
}
|
||||
},
|
||||
'sort': {
|
||||
'undo': function (obj) {
|
||||
var node = obj.params.node;
|
||||
node.hideChilds();
|
||||
node.sort = obj.params.oldSort;
|
||||
node.childs = obj.params.oldChilds;
|
||||
node.showChilds();
|
||||
},
|
||||
'redo': function (obj) {
|
||||
var node = obj.params.node;
|
||||
node.hideChilds();
|
||||
node.sort = obj.params.newSort;
|
||||
node.childs = obj.params.newChilds;
|
||||
node.showChilds();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: restore the original caret position and selection with each undo
|
||||
// TODO: implement history for actions "expand", "collapse", "scroll", "setDocument"
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* The method onChange is executed when the History is changed, and can
|
||||
* be overloaded.
|
||||
*/
|
||||
JSONEditor.History.prototype.onChange = function () {};
|
||||
|
||||
/**
|
||||
* Add a new action to the history
|
||||
* @param {String} action The executed action. Available actions: "editField",
|
||||
* "editValue", "changeType", "appendNode",
|
||||
* "removeNode", "duplicateNode", "moveNode"
|
||||
* @param {Object} params Object containing parameters describing the change.
|
||||
* The parameters in params depend on the action (for
|
||||
* example for "editValue" the Node, old value, and new
|
||||
* value are provided). params contains all information
|
||||
* needed to undo or redo the action.
|
||||
*/
|
||||
JSONEditor.History.prototype.add = function (action, params) {
|
||||
this.index++;
|
||||
this.history[this.index] = {
|
||||
'action': action,
|
||||
'params': params,
|
||||
'timestamp': new Date()
|
||||
};
|
||||
|
||||
// remove redo actions which are invalid now
|
||||
if (this.index < this.history.length - 1) {
|
||||
this.history.splice(this.index + 1, this.history.length - this.index - 1);
|
||||
}
|
||||
|
||||
// fire onchange event
|
||||
this.onChange();
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear history
|
||||
*/
|
||||
JSONEditor.History.prototype.clear = function () {
|
||||
this.history = [];
|
||||
this.index = -1;
|
||||
|
||||
// fire onchange event
|
||||
this.onChange();
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if there is an action available for undo
|
||||
* @return {Boolean} canUndo
|
||||
*/
|
||||
JSONEditor.History.prototype.canUndo = function () {
|
||||
return (this.index >= 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if there is an action available for redo
|
||||
* @return {Boolean} canRedo
|
||||
*/
|
||||
JSONEditor.History.prototype.canRedo = function () {
|
||||
return (this.index < this.history.length - 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Undo the last action
|
||||
*/
|
||||
JSONEditor.History.prototype.undo = function () {
|
||||
if (this.canUndo()) {
|
||||
var obj = this.history[this.index];
|
||||
if (obj) {
|
||||
var action = this.actions[obj.action];
|
||||
if (action && action.undo) {
|
||||
action.undo(obj);
|
||||
}
|
||||
else {
|
||||
console.log('Error: unknown action "' + obj.action + '"');
|
||||
}
|
||||
}
|
||||
this.index--;
|
||||
|
||||
// fire onchange event
|
||||
this.onChange();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Redo the last action
|
||||
*/
|
||||
JSONEditor.History.prototype.redo = function () {
|
||||
if (this.canRedo()) {
|
||||
this.index++;
|
||||
|
||||
var obj = this.history[this.index];
|
||||
if (obj) {
|
||||
if (obj) {
|
||||
var action = this.actions[obj.action];
|
||||
if (action && action.redo) {
|
||||
action.redo(obj);
|
||||
}
|
||||
else {
|
||||
console.log('Error: unknown action "' + obj.action + '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fire onchange event
|
||||
this.onChange();
|
||||
}
|
||||
};
|
|
@ -0,0 +1,786 @@
|
|||
/*!
|
||||
* @file jsoneditor.js
|
||||
*
|
||||
* @brief
|
||||
* JSONEditor is a web-based tool to view, edit, and format JSON.
|
||||
* It shows data a clear, editable treeview.
|
||||
*
|
||||
* Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+
|
||||
*
|
||||
* @license
|
||||
* This json editor is open sourced with the intention to use the editor as
|
||||
* a component in your own application. Not to just copy and monetize the editor
|
||||
* as it is.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
* @date 2013-01-01
|
||||
*/
|
||||
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.indexOf,
|
||||
// so we define it here in that case
|
||||
// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/
|
||||
if(!Array.prototype.indexOf) {
|
||||
Array.prototype.indexOf = function(obj){
|
||||
for(var i = 0; i < this.length; i++){
|
||||
if(this[i] == obj){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.forEach,
|
||||
// so we define it here in that case
|
||||
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
|
||||
if (!Array.prototype.forEach) {
|
||||
Array.prototype.forEach = function(fn, scope) {
|
||||
for(var i = 0, len = this.length; i < len; ++i) {
|
||||
fn.call(scope || this, this[i], i, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// define variable JSON, needed for correct error handling on IE7 and older
|
||||
var JSON;
|
||||
|
||||
/**
|
||||
* JSONEditor
|
||||
* @param {Element} container Container element
|
||||
* @param {Object} [options] Object with options. available options:
|
||||
* {String} mode Editor mode. Available values:
|
||||
* 'editor' (default), 'viewer'.
|
||||
* {Boolean} search Enable search box.
|
||||
* True by default
|
||||
* {Boolean} history Enable history (undo/redo).
|
||||
* True by default
|
||||
* {function} change Callback method, triggered
|
||||
* on change of contents
|
||||
* {String} name Field name for the root node.
|
||||
* @param {Object | undefined} json JSON object
|
||||
*/
|
||||
var JSONEditor = function (container, options, json) {
|
||||
// check availability of JSON parser (not available in IE7 and older)
|
||||
if (!JSON) {
|
||||
throw new Error ('Your browser does not support JSON. \n\n' +
|
||||
'Please install the newest version of your browser.\n' +
|
||||
'(all modern browsers support JSON).');
|
||||
}
|
||||
|
||||
if (!container) {
|
||||
throw new Error('No container element provided.');
|
||||
}
|
||||
this.container = container;
|
||||
this.dom = {};
|
||||
this.highlighter = new JSONEditor.Highlighter();
|
||||
|
||||
this._setOptions(options);
|
||||
|
||||
if (this.options.history && this.editable) {
|
||||
this.history = new JSONEditor.History(this);
|
||||
}
|
||||
|
||||
this._createFrame();
|
||||
this._createTable();
|
||||
|
||||
this.set(json || {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize and set default options
|
||||
* @param {Object} [options] Object with options. available options:
|
||||
* {String} mode Editor mode. Available values:
|
||||
* 'editor' (default), 'viewer'.
|
||||
* {Boolean} search Enable search box.
|
||||
* True by default.
|
||||
* {Boolean} history Enable history (undo/redo).
|
||||
* True by default.
|
||||
* {function} change Callback method, triggered
|
||||
* on change of contents.
|
||||
* {String} name Field name for the root node.
|
||||
* @private
|
||||
*/
|
||||
JSONEditor.prototype._setOptions = function (options) {
|
||||
this.options = {
|
||||
search: true,
|
||||
history: true,
|
||||
mode: 'editor',
|
||||
name: undefined // field name of root node
|
||||
};
|
||||
|
||||
// copy all options
|
||||
if (options) {
|
||||
for (var prop in options) {
|
||||
if (options.hasOwnProperty(prop)) {
|
||||
this.options[prop] = options[prop];
|
||||
}
|
||||
}
|
||||
|
||||
// check for deprecated options
|
||||
if (options['enableSearch']) {
|
||||
// deprecated since version 1.6.0, 2012-11-03
|
||||
this.options.search = options['enableSearch'];
|
||||
console.log('WARNING: Option "enableSearch" is deprecated. Use "search" instead.');
|
||||
}
|
||||
if (options['enableSearch']) {
|
||||
// deprecated since version 1.6.0, 2012-11-03
|
||||
this.options.search = options['enableSearch'];
|
||||
console.log('WARNING: Option "enableHistory" is deprecated. Use "history" instead.');
|
||||
}
|
||||
}
|
||||
|
||||
// interpret the options
|
||||
this.editable = (this.options.mode != 'viewer');
|
||||
};
|
||||
|
||||
// node currently being edited
|
||||
JSONEditor.focusNode = undefined;
|
||||
|
||||
/**
|
||||
* Set JSON object in editor
|
||||
* @param {Object | undefined} json JSON data
|
||||
* @param {String} [name] Optional field name for the root node.
|
||||
* Can also be set using setName(name).
|
||||
*/
|
||||
JSONEditor.prototype.set = function (json, name) {
|
||||
// adjust field name for root node
|
||||
if (name) {
|
||||
this.options.name = name;
|
||||
}
|
||||
|
||||
// verify if json is valid JSON, ignore when a function
|
||||
if (json instanceof Function || (json === undefined)) {
|
||||
this.clear();
|
||||
}
|
||||
else {
|
||||
this.content.removeChild(this.table); // Take the table offline
|
||||
|
||||
// replace the root node
|
||||
var params = {
|
||||
'field': this.options.name,
|
||||
'value': json
|
||||
};
|
||||
var node = new JSONEditor.Node(this, params);
|
||||
this._setRoot(node);
|
||||
|
||||
// expand
|
||||
var recurse = false;
|
||||
this.node.expand(recurse);
|
||||
|
||||
this.content.appendChild(this.table); // Put the table online again
|
||||
}
|
||||
|
||||
// TODO: maintain history, store last state and previous document
|
||||
if (this.history) {
|
||||
this.history.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get JSON object from editor
|
||||
* @return {Object | undefined} json
|
||||
*/
|
||||
JSONEditor.prototype.get = function () {
|
||||
// remove focus from currently edited node
|
||||
if (JSONEditor.focusNode) {
|
||||
JSONEditor.focusNode.blur();
|
||||
}
|
||||
|
||||
if (this.node) {
|
||||
return this.node.getValue();
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a field name for the root node.
|
||||
* @param {String | undefined} name
|
||||
*/
|
||||
JSONEditor.prototype.setName = function (name) {
|
||||
this.options.name = name;
|
||||
if (this.node) {
|
||||
this.node.updateField(this.options.name);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the field name for the root node.
|
||||
* @return {String | undefined} name
|
||||
*/
|
||||
JSONEditor.prototype.getName = function () {
|
||||
return this.options.name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the root node from the editor
|
||||
*/
|
||||
JSONEditor.prototype.clear = function () {
|
||||
if (this.node) {
|
||||
this.node.collapse();
|
||||
this.tbody.removeChild(this.node.getDom());
|
||||
delete this.node;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the root node for the json editor
|
||||
* @param {JSONEditor.Node} node
|
||||
* @private
|
||||
*/
|
||||
JSONEditor.prototype._setRoot = function (node) {
|
||||
this.clear();
|
||||
|
||||
this.node = node;
|
||||
|
||||
// append to the dom
|
||||
this.tbody.appendChild(node.getDom());
|
||||
};
|
||||
|
||||
/**
|
||||
* Search text in all nodes
|
||||
* The nodes will be expanded when the text is found one of its childs,
|
||||
* else it will be collapsed. Searches are case insensitive.
|
||||
* @param {String} text
|
||||
* @return {Object[]} results Array with nodes containing the search results
|
||||
* The result objects contains fields:
|
||||
* - {JSONEditor.Node} node,
|
||||
* - {String} elem the dom element name where
|
||||
* the result is found ('field' or
|
||||
* 'value')
|
||||
*/
|
||||
JSONEditor.prototype.search = function (text) {
|
||||
var results;
|
||||
if (this.node) {
|
||||
this.content.removeChild(this.table); // Take the table offline
|
||||
results = this.node.search(text);
|
||||
this.content.appendChild(this.table); // Put the table online again
|
||||
}
|
||||
else {
|
||||
results = [];
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand all nodes
|
||||
*/
|
||||
JSONEditor.prototype.expandAll = function () {
|
||||
if (this.node) {
|
||||
this.content.removeChild(this.table); // Take the table offline
|
||||
this.node.expand();
|
||||
this.content.appendChild(this.table); // Put the table online again
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Collapse all nodes
|
||||
*/
|
||||
JSONEditor.prototype.collapseAll = function () {
|
||||
if (this.node) {
|
||||
this.content.removeChild(this.table); // Take the table offline
|
||||
this.node.collapse();
|
||||
this.content.appendChild(this.table); // Put the table online again
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The method onChange is called whenever a field or value is changed, created,
|
||||
* deleted, duplicated, etc.
|
||||
* @param {String} action Change action. Available values: "editField",
|
||||
* "editValue", "changeType", "appendNode",
|
||||
* "removeNode", "duplicateNode", "moveNode", "expand",
|
||||
* "collapse".
|
||||
* @param {Object} params Object containing parameters describing the change.
|
||||
* The parameters in params depend on the action (for
|
||||
* example for "editValue" the Node, old value, and new
|
||||
* value are provided). params contains all information
|
||||
* needed to undo or redo the action.
|
||||
*/
|
||||
JSONEditor.prototype.onAction = function (action, params) {
|
||||
// add an action to the history
|
||||
if (this.history) {
|
||||
this.history.add(action, params);
|
||||
}
|
||||
|
||||
// trigger the onChange callback
|
||||
if (this.options.change) {
|
||||
try {
|
||||
this.options.change();
|
||||
}
|
||||
catch (err) {
|
||||
console.log('Error in change callback: ', err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Start autoscrolling when given mouse position is above the top of the
|
||||
* editor contents, or below the bottom.
|
||||
* @param {Number} mouseY Absolute mouse position in pixels
|
||||
*/
|
||||
JSONEditor.prototype.startAutoScroll = function (mouseY) {
|
||||
var me = this;
|
||||
var content = this.content;
|
||||
var top = JSONEditor.util.getAbsoluteTop(content);
|
||||
var height = content.clientHeight;
|
||||
var bottom = top + height;
|
||||
var margin = 24;
|
||||
var interval = 50; // ms
|
||||
|
||||
if ((mouseY < top + margin) && content.scrollTop > 0) {
|
||||
this.autoScrollStep = ((top + margin) - mouseY) / 3;
|
||||
}
|
||||
else if (mouseY > bottom - margin &&
|
||||
height + content.scrollTop < content.scrollHeight) {
|
||||
this.autoScrollStep = ((bottom - margin) - mouseY) / 3;
|
||||
}
|
||||
else {
|
||||
this.autoScrollStep = undefined;
|
||||
}
|
||||
|
||||
if (this.autoScrollStep) {
|
||||
if (!this.autoScrollTimer) {
|
||||
this.autoScrollTimer = setInterval(function () {
|
||||
if (me.autoScrollStep) {
|
||||
content.scrollTop -= me.autoScrollStep;
|
||||
}
|
||||
else {
|
||||
me.stopAutoScroll();
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.stopAutoScroll();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop auto scrolling. Only applicable when scrolling
|
||||
*/
|
||||
JSONEditor.prototype.stopAutoScroll = function () {
|
||||
if (this.autoScrollTimer) {
|
||||
clearTimeout(this.autoScrollTimer);
|
||||
delete this.autoScrollTimer;
|
||||
}
|
||||
if (this.autoScrollStep) {
|
||||
delete this.autoScrollStep;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the focus to the JSONEditor. A hidden input field will be created
|
||||
* which captures key events
|
||||
*/
|
||||
// TODO: use the focus method?
|
||||
JSONEditor.prototype.focus = function () {
|
||||
/*
|
||||
if (!this.dom.focus) {
|
||||
this.dom.focus = document.createElement('input');
|
||||
this.dom.focus.className = 'jsoneditor-hidden-focus';
|
||||
|
||||
var editor = this;
|
||||
this.dom.focus.onblur = function () {
|
||||
// remove itself
|
||||
if (editor.dom.focus) {
|
||||
var focus = editor.dom.focus;
|
||||
delete editor.dom.focus;
|
||||
editor.frame.removeChild(focus);
|
||||
}
|
||||
};
|
||||
|
||||
// attach the hidden input box to the DOM
|
||||
if (this.frame.firstChild) {
|
||||
this.frame.insertBefore(this.dom.focus, this.frame.firstChild);
|
||||
}
|
||||
else {
|
||||
this.frame.appendChild(this.dom.focus);
|
||||
}
|
||||
}
|
||||
this.dom.focus.focus();
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* Adjust the scroll position such that given top position is shown at 1/4
|
||||
* of the window height.
|
||||
* @param {Number} top
|
||||
*/
|
||||
JSONEditor.prototype.scrollTo = function (top) {
|
||||
var content = this.content;
|
||||
if (content) {
|
||||
// cancel any running animation
|
||||
var editor = this;
|
||||
if (editor.animateTimeout) {
|
||||
clearTimeout(editor.animateTimeout);
|
||||
delete editor.animateTimeout;
|
||||
}
|
||||
|
||||
// calculate final scroll position
|
||||
var height = content.clientHeight;
|
||||
var bottom = content.scrollHeight - height;
|
||||
var finalScrollTop = Math.min(Math.max(top - height / 4, 0), bottom);
|
||||
|
||||
// animate towards the new scroll position
|
||||
var animate = function () {
|
||||
var scrollTop = content.scrollTop;
|
||||
var diff = (finalScrollTop - scrollTop);
|
||||
if (Math.abs(diff) > 3) {
|
||||
content.scrollTop += diff / 3;
|
||||
editor.animateTimeout = setTimeout(animate, 50);
|
||||
}
|
||||
};
|
||||
animate();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test if an element is a child of a parent element.
|
||||
* @param {Element} child
|
||||
* @param {Element} parent
|
||||
* @param {boolean} [includeParent] if true (default), the method will return
|
||||
* true too when the child is the parent.
|
||||
* @return {boolean} isChild
|
||||
*/
|
||||
JSONEditor.isChildOf = function (child, parent, includeParent) {
|
||||
var e = child;
|
||||
if (includeParent != false && e == parent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
e = e.parentNode;
|
||||
while (e) {
|
||||
if (e == parent) {
|
||||
return true;
|
||||
}
|
||||
e = e.parentNode;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create main frame
|
||||
* @private
|
||||
*/
|
||||
JSONEditor.prototype._createFrame = function () {
|
||||
// create the frame
|
||||
this.container.innerHTML = '';
|
||||
this.frame = document.createElement('div');
|
||||
this.frame.className = 'jsoneditor-frame';
|
||||
this.container.appendChild(this.frame);
|
||||
|
||||
// create one global event listener to handle all events from all nodes
|
||||
var editor = this;
|
||||
// TODO: move this onEvent to JSONEditor.prototype.onEvent
|
||||
var onEvent = function (event) {
|
||||
event = event || window.event;
|
||||
var target = event.target || event.srcElement;
|
||||
|
||||
if (event.type == 'keydown') {
|
||||
editor.onKeyDown(event);
|
||||
}
|
||||
|
||||
var node = JSONEditor.getNodeFromTarget(target);
|
||||
if (node) {
|
||||
node.onEvent(event);
|
||||
}
|
||||
};
|
||||
this.frame.onclick = function (event) {
|
||||
onEvent(event);
|
||||
|
||||
// prevent default submit action when JSONEditor is located inside a form
|
||||
JSONEditor.util.preventDefault(event);
|
||||
};
|
||||
this.frame.onchange = onEvent;
|
||||
this.frame.onkeydown = onEvent;
|
||||
this.frame.onkeyup = onEvent;
|
||||
this.frame.oncut = onEvent;
|
||||
this.frame.onpaste = onEvent;
|
||||
this.frame.onmousedown = onEvent;
|
||||
this.frame.onmouseup = onEvent;
|
||||
this.frame.onmouseover = onEvent;
|
||||
this.frame.onmouseout = onEvent;
|
||||
// Note: focus and blur events do not propagate, therefore they defined
|
||||
// using an eventListener with useCapture=true
|
||||
// see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
|
||||
JSONEditor.util.addEventListener(this.frame, 'focus', onEvent, true);
|
||||
JSONEditor.util.addEventListener(this.frame, 'blur', onEvent, true);
|
||||
this.frame.onfocusin = onEvent; // for IE
|
||||
this.frame.onfocusout = onEvent; // for IE
|
||||
|
||||
// create menu
|
||||
this.menu = document.createElement('div');
|
||||
this.menu.className = 'jsoneditor-menu';
|
||||
this.frame.appendChild(this.menu);
|
||||
|
||||
// create expand all button
|
||||
var expandAll = document.createElement('button');
|
||||
expandAll.className = 'jsoneditor-menu jsoneditor-expand-all';
|
||||
expandAll.title = 'Expand all fields';
|
||||
expandAll.onclick = function () {
|
||||
editor.expandAll();
|
||||
};
|
||||
this.menu.appendChild(expandAll);
|
||||
|
||||
// create expand all button
|
||||
var collapseAll = document.createElement('button');
|
||||
collapseAll.title = 'Collapse all fields';
|
||||
collapseAll.className = 'jsoneditor-menu jsoneditor-collapse-all';
|
||||
collapseAll.onclick = function () {
|
||||
editor.collapseAll();
|
||||
};
|
||||
this.menu.appendChild(collapseAll);
|
||||
|
||||
// create undo/redo buttons
|
||||
if (this.history) {
|
||||
// create separator
|
||||
var separator = document.createElement('span');
|
||||
separator.innerHTML = ' ';
|
||||
this.menu.appendChild(separator);
|
||||
|
||||
// create undo button
|
||||
var undo = document.createElement('button');
|
||||
undo.className = 'jsoneditor-menu jsoneditor-undo';
|
||||
undo.title = 'Undo last action';
|
||||
undo.onclick = function () {
|
||||
editor._onUndo();
|
||||
};
|
||||
this.menu.appendChild(undo);
|
||||
this.dom.undo = undo;
|
||||
|
||||
// create redo button
|
||||
var redo = document.createElement('button');
|
||||
redo.className = 'jsoneditor-menu jsoneditor-redo';
|
||||
redo.title = 'Redo';
|
||||
redo.onclick = function () {
|
||||
editor._onRedo();
|
||||
};
|
||||
this.menu.appendChild(redo);
|
||||
this.dom.redo = redo;
|
||||
|
||||
// register handler for onchange of history
|
||||
this.history.onChange = function () {
|
||||
undo.disabled = !editor.history.canUndo();
|
||||
redo.disabled = !editor.history.canRedo();
|
||||
};
|
||||
this.history.onChange();
|
||||
}
|
||||
|
||||
// create search box
|
||||
if (this.options.search) {
|
||||
this.searchBox = new JSONEditor.SearchBox(this, this.menu);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform an undo action
|
||||
* @private
|
||||
*/
|
||||
JSONEditor.prototype._onUndo = function () {
|
||||
if (this.history) {
|
||||
// undo last action
|
||||
this.history.undo();
|
||||
|
||||
// trigger change callback
|
||||
if (this.options.change) {
|
||||
this.options.change();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform a redo action
|
||||
* @private
|
||||
*/
|
||||
JSONEditor.prototype._onRedo = function () {
|
||||
if (this.history) {
|
||||
// redo last action
|
||||
editor.history.redo();
|
||||
|
||||
// trigger change callback
|
||||
if (editor.options.change) {
|
||||
editor.options.change();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler for keydown. Handles shortcut keys
|
||||
* @param {Event} event
|
||||
*/
|
||||
JSONEditor.prototype.onKeyDown = function (event) {
|
||||
var keynum = event.which || event.keyCode;
|
||||
var ctrlKey = event.ctrlKey;
|
||||
var shiftKey = event.shiftKey;
|
||||
var handled = false;
|
||||
|
||||
if (this.searchBox) {
|
||||
if (ctrlKey && keynum == 70) { // Ctrl+F
|
||||
this.searchBox.dom.search.focus();
|
||||
this.searchBox.dom.search.select();
|
||||
handled = true;
|
||||
}
|
||||
else if (keynum == 114 || (ctrlKey && keynum == 71)) { // F3 or Ctrl+G
|
||||
if (!shiftKey) {
|
||||
// select next search result (F3 or Ctrl+G)
|
||||
this.searchBox.next();
|
||||
}
|
||||
else {
|
||||
// select previous search result (Shift+F3 or Ctrl+Shift+G)
|
||||
this.searchBox.previous();
|
||||
}
|
||||
|
||||
// set selection to the current
|
||||
this.searchBox.focusActiveResult();
|
||||
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.history) {
|
||||
if (ctrlKey && !shiftKey && keynum == 90) { // Ctrl+Z
|
||||
// undo
|
||||
this._onUndo();
|
||||
handled = true;
|
||||
}
|
||||
else if (ctrlKey && shiftKey && keynum == 90) { // Ctrl+Shift+Z
|
||||
// redo
|
||||
this._onRedo();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
JSONEditor.util.preventDefault(event);
|
||||
JSONEditor.util.stopPropagation(event);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create main table
|
||||
* @private
|
||||
*/
|
||||
JSONEditor.prototype._createTable = function () {
|
||||
var contentOuter = document.createElement('div');
|
||||
contentOuter.className = 'jsoneditor-content-outer';
|
||||
this.contentOuter = contentOuter;
|
||||
|
||||
this.content = document.createElement('div');
|
||||
this.content.className = 'jsoneditor-content';
|
||||
contentOuter.appendChild(this.content);
|
||||
|
||||
this.table = document.createElement('table');
|
||||
this.table.className = 'jsoneditor-table';
|
||||
this.content.appendChild(this.table);
|
||||
|
||||
// IE8 does not handle overflow='auto' correctly.
|
||||
// Therefore, set overflow to 'scroll'
|
||||
var ieVersion = JSONEditor.util.getInternetExplorerVersion();
|
||||
if (ieVersion == 8) {
|
||||
this.content.style.overflow = 'scroll';
|
||||
}
|
||||
|
||||
// create colgroup where the first two columns don't have a fixed
|
||||
// width, and the edit columns do have a fixed width
|
||||
var col;
|
||||
this.colgroupContent = document.createElement('colgroup');
|
||||
col = document.createElement('col');
|
||||
col.width = "24px";
|
||||
this.colgroupContent.appendChild(col);
|
||||
col = document.createElement('col');
|
||||
col.width = "24px";
|
||||
this.colgroupContent.appendChild(col);
|
||||
col = document.createElement('col');
|
||||
this.colgroupContent.appendChild(col);
|
||||
this.table.appendChild(this.colgroupContent);
|
||||
|
||||
this.tbody = document.createElement('tbody');
|
||||
this.table.appendChild(this.tbody);
|
||||
|
||||
this.frame.appendChild(contentOuter);
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the node from an event target
|
||||
* @param {Node} target
|
||||
* @return {JSONEditor.Node | undefined} node or undefined when not found
|
||||
*/
|
||||
JSONEditor.getNodeFromTarget = function (target) {
|
||||
while (target) {
|
||||
if (target.node) {
|
||||
return target.node;
|
||||
}
|
||||
target = target.parentNode;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse JSON using the parser built-in in the browser.
|
||||
* On exception, the jsonString is validated and a detailed error is thrown.
|
||||
* @param {String} jsonString
|
||||
*/
|
||||
JSONEditor.parse = function (jsonString) {
|
||||
try {
|
||||
return JSON.parse(jsonString);
|
||||
}
|
||||
catch (err) {
|
||||
// get a detailed error message using validate
|
||||
var message = JSONEditor.validate(jsonString) || err;
|
||||
throw new Error(message);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate a string containing a JSON object
|
||||
* This method uses JSONLint to validate the String. If JSONLint is not
|
||||
* available, the built-in JSON parser of the browser is used.
|
||||
* @param {String} jsonString String with an (invalid) JSON object
|
||||
* @return {String | undefined} Returns undefined when the string is valid JSON,
|
||||
* returns a string with an error message when
|
||||
* the data is invalid
|
||||
*/
|
||||
JSONEditor.validate = function (jsonString) {
|
||||
var message = undefined;
|
||||
|
||||
try {
|
||||
if (window.jsonlint) {
|
||||
window.jsonlint.parse(jsonString);
|
||||
}
|
||||
else {
|
||||
JSON.parse(jsonString);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
message = '<pre class="error">' + err.toString() + '</pre>';
|
||||
if (window.jsonlint) {
|
||||
message +=
|
||||
'<a class="error" href="http://zaach.github.com/jsonlint/" target="_blank">' +
|
||||
'validated by jsonlint' +
|
||||
'</a>';
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
|
@ -0,0 +1,175 @@
|
|||
/**
|
||||
* @license
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a JSONFormatter and attach it to given container
|
||||
* @constructor JSONFormatter
|
||||
* @param {Element} container
|
||||
* @param {Object} [options] Object with options. available options:
|
||||
* {Number} indentation Number of indentation
|
||||
* spaces. 4 by default.
|
||||
* {function} change Callback method
|
||||
* triggered on change
|
||||
* @param {JSON | String} [json] initial contents of the formatter
|
||||
*/
|
||||
JSONFormatter = function (container, options, json) {
|
||||
// check availability of JSON parser (not available in IE7 and older)
|
||||
if (!JSON) {
|
||||
throw new Error('Your browser does not support JSON. \n\n' +
|
||||
'Please install the newest version of your browser.\n' +
|
||||
'(all modern browsers support JSON).');
|
||||
}
|
||||
|
||||
this.container = container;
|
||||
this.indentation = 4; // number of spaces
|
||||
|
||||
this.width = container.clientWidth;
|
||||
this.height = container.clientHeight;
|
||||
|
||||
this.frame = document.createElement('div');
|
||||
this.frame.className = "jsoneditor-frame";
|
||||
this.frame.onclick = function (event) {
|
||||
// prevent default submit action when JSONFormatter is located inside a form
|
||||
JSONEditor.util.preventDefault(event);
|
||||
};
|
||||
|
||||
// create menu
|
||||
this.menu = document.createElement('div');
|
||||
this.menu.className = 'jsoneditor-menu';
|
||||
this.frame.appendChild(this.menu);
|
||||
|
||||
// create format button
|
||||
var buttonFormat = document.createElement('button');
|
||||
//buttonFormat.innerHTML = 'Format';
|
||||
buttonFormat.className = 'jsoneditor-menu jsoneditor-format';
|
||||
buttonFormat.title = 'Format JSON data, with proper indentation and line feeds';
|
||||
//buttonFormat.className = 'jsoneditor-button';
|
||||
this.menu.appendChild(buttonFormat);
|
||||
|
||||
// create compact button
|
||||
var buttonCompact = document.createElement('button');
|
||||
//buttonCompact.innerHTML = 'Compact';
|
||||
buttonCompact.className = 'jsoneditor-menu jsoneditor-compact';
|
||||
buttonCompact.title = 'Compact JSON data, remove all whitespaces';
|
||||
//buttonCompact.className = 'jsoneditor-button';
|
||||
this.menu.appendChild(buttonCompact);
|
||||
|
||||
this.content = document.createElement('div');
|
||||
this.content.className = 'jsonformatter-content';
|
||||
this.frame.appendChild(this.content);
|
||||
|
||||
this.textarea = document.createElement('textarea');
|
||||
this.textarea.className = "jsonformatter-textarea";
|
||||
this.textarea.spellcheck = false;
|
||||
this.content.appendChild(this.textarea);
|
||||
|
||||
var textarea = this.textarea;
|
||||
|
||||
// read the options
|
||||
if (options) {
|
||||
if (options.change) {
|
||||
// register on change event
|
||||
if (this.textarea.oninput === null) {
|
||||
this.textarea.oninput = function () {
|
||||
options.change();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// oninput is undefined. For IE8-
|
||||
this.textarea.onchange = function () {
|
||||
options.change();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.indentation) {
|
||||
this.indentation = Number(options.indentation);
|
||||
}
|
||||
}
|
||||
|
||||
var me = this;
|
||||
buttonFormat.onclick = function () {
|
||||
try {
|
||||
var json = JSONEditor.parse(textarea.value);
|
||||
textarea.value = JSON.stringify(json, null, me.indentation);
|
||||
}
|
||||
catch (err) {
|
||||
me.onError(err);
|
||||
}
|
||||
};
|
||||
buttonCompact.onclick = function () {
|
||||
try {
|
||||
var json = JSONEditor.parse(textarea.value);
|
||||
textarea.value = JSON.stringify(json);
|
||||
}
|
||||
catch (err) {
|
||||
me.onError(err);
|
||||
}
|
||||
};
|
||||
|
||||
this.container.appendChild(this.frame);
|
||||
|
||||
// load initial json object or string
|
||||
if (typeof(json) == 'string') {
|
||||
this.setText(json);
|
||||
}
|
||||
else {
|
||||
this.set(json);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This method is executed on error.
|
||||
* It can be overwritten for each instance of the JSONFormatter
|
||||
* @param {String} err
|
||||
*/
|
||||
JSONFormatter.prototype.onError = function(err) {
|
||||
// action should be implemented for the instance
|
||||
};
|
||||
|
||||
/**
|
||||
* Set json data in the formatter
|
||||
* @param {Object} json
|
||||
*/
|
||||
JSONFormatter.prototype.set = function(json) {
|
||||
this.textarea.value = JSON.stringify(json, null, this.indentation);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get json data from the formatter
|
||||
* @return {Object} json
|
||||
*/
|
||||
JSONFormatter.prototype.get = function() {
|
||||
return JSONEditor.parse(this.textarea.value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the text contents of the JSONFormatter
|
||||
* @return {String} text
|
||||
*/
|
||||
JSONFormatter.prototype.getText = function() {
|
||||
return this.textarea.value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the text contents of the JSONFormatter
|
||||
* @param {String} text
|
||||
*/
|
||||
JSONFormatter.prototype.setText = function(text) {
|
||||
this.textarea.value = text;
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,309 @@
|
|||
/**
|
||||
* @license
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @constructor JSONEditor.SearchBox
|
||||
* Create a search box in given HTML container
|
||||
* @param {JSONEditor} editor The JSON Editor to attach to
|
||||
* @param {Element} container HTML container element of where to create the
|
||||
* search box
|
||||
*/
|
||||
JSONEditor.SearchBox = function(editor, container) {
|
||||
var searchBox = this;
|
||||
|
||||
this.editor = editor;
|
||||
this.timeout = undefined;
|
||||
this.delay = 200; // ms
|
||||
this.lastText = undefined;
|
||||
|
||||
this.dom = {};
|
||||
this.dom.container = container;
|
||||
|
||||
var table = document.createElement('table');
|
||||
this.dom.table = table;
|
||||
table.className = 'jsoneditor-search';
|
||||
container.appendChild(table);
|
||||
var tbody = document.createElement('tbody');
|
||||
this.dom.tbody = tbody;
|
||||
table.appendChild(tbody);
|
||||
var tr = document.createElement('tr');
|
||||
tbody.appendChild(tr);
|
||||
|
||||
var td = document.createElement('td');
|
||||
td.className = 'jsoneditor-search';
|
||||
tr.appendChild(td);
|
||||
var results = document.createElement('div');
|
||||
this.dom.results = results;
|
||||
results.className = 'jsoneditor-search-results';
|
||||
td.appendChild(results);
|
||||
|
||||
td = document.createElement('td');
|
||||
td.className = 'jsoneditor-search';
|
||||
tr.appendChild(td);
|
||||
var divInput = document.createElement('div');
|
||||
this.dom.input = divInput;
|
||||
divInput.className = 'jsoneditor-search';
|
||||
divInput.title = 'Search fields and values';
|
||||
td.appendChild(divInput);
|
||||
|
||||
// table to contain the text input and search button
|
||||
var tableInput = document.createElement('table');
|
||||
tableInput.className = 'jsoneditor-search-input';
|
||||
divInput.appendChild(tableInput);
|
||||
var tbodySearch = document.createElement('tbody');
|
||||
tableInput.appendChild(tbodySearch);
|
||||
tr = document.createElement('tr');
|
||||
tbodySearch.appendChild(tr);
|
||||
|
||||
var refreshSearch = document.createElement('button');
|
||||
refreshSearch.className = 'jsoneditor-search-refresh';
|
||||
td = document.createElement('td');
|
||||
td.appendChild(refreshSearch);
|
||||
tr.appendChild(td);
|
||||
|
||||
var search = document.createElement('input');
|
||||
this.dom.search = search;
|
||||
search.className = 'jsoneditor-search';
|
||||
search.oninput = function (event) {
|
||||
searchBox.onDelayedSearch(event);
|
||||
};
|
||||
search.onchange = function (event) { // For IE 8
|
||||
searchBox.onSearch(event);
|
||||
};
|
||||
search.onkeydown = function (event) {
|
||||
searchBox.onKeyDown(event);
|
||||
};
|
||||
search.onkeyup = function (event) {
|
||||
searchBox.onKeyUp(event);
|
||||
};
|
||||
refreshSearch.onclick = function (event) {
|
||||
search.select();
|
||||
};
|
||||
|
||||
// TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819
|
||||
td = document.createElement('td');
|
||||
td.appendChild(search);
|
||||
tr.appendChild(td);
|
||||
|
||||
var searchNext = document.createElement('button');
|
||||
searchNext.title = 'Next result (Enter)';
|
||||
searchNext.className = 'jsoneditor-search-next';
|
||||
searchNext.onclick = function () {
|
||||
searchBox.next();
|
||||
};
|
||||
td = document.createElement('td');
|
||||
td.appendChild(searchNext);
|
||||
tr.appendChild(td);
|
||||
|
||||
var searchPrevious = document.createElement('button');
|
||||
searchPrevious.title = 'Previous result (Shift+Enter)';
|
||||
searchPrevious.className = 'jsoneditor-search-previous';
|
||||
searchPrevious.onclick = function () {
|
||||
searchBox.previous();
|
||||
};
|
||||
td = document.createElement('td');
|
||||
td.appendChild(searchPrevious);
|
||||
tr.appendChild(td);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Go to the next search result
|
||||
*/
|
||||
JSONEditor.SearchBox.prototype.next = function() {
|
||||
if (this.results != undefined) {
|
||||
var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0;
|
||||
if (index > this.results.length - 1) {
|
||||
index = 0;
|
||||
}
|
||||
this.setActiveResult(index);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Go to the prevous search result
|
||||
*/
|
||||
JSONEditor.SearchBox.prototype.previous = function() {
|
||||
if (this.results != undefined) {
|
||||
var max = this.results.length - 1;
|
||||
var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max;
|
||||
if (index < 0) {
|
||||
index = max;
|
||||
}
|
||||
this.setActiveResult(index);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set new value for the current active result
|
||||
* @param {Number} index
|
||||
*/
|
||||
JSONEditor.SearchBox.prototype.setActiveResult = function(index) {
|
||||
// de-activate current active result
|
||||
if (this.activeResult) {
|
||||
var prevNode = this.activeResult.node;
|
||||
var prevElem = this.activeResult.elem;
|
||||
if (prevElem == 'field') {
|
||||
delete prevNode.searchFieldActive;
|
||||
}
|
||||
else {
|
||||
delete prevNode.searchValueActive;
|
||||
}
|
||||
prevNode.updateDom();
|
||||
}
|
||||
|
||||
if (!this.results || !this.results[index]) {
|
||||
// out of range, set to undefined
|
||||
this.resultIndex = undefined;
|
||||
this.activeResult = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
this.resultIndex = index;
|
||||
|
||||
// set new node active
|
||||
var node = this.results[this.resultIndex].node;
|
||||
var elem = this.results[this.resultIndex].elem;
|
||||
if (elem == 'field') {
|
||||
node.searchFieldActive = true;
|
||||
}
|
||||
else {
|
||||
node.searchValueActive = true;
|
||||
}
|
||||
this.activeResult = this.results[this.resultIndex];
|
||||
node.updateDom();
|
||||
|
||||
node.scrollTo();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the focus to the currently active result. If there is no currently
|
||||
* active result, the next search result will get focus
|
||||
*/
|
||||
JSONEditor.SearchBox.prototype.focusActiveResult = function() {
|
||||
if (!this.activeResult) {
|
||||
this.next();
|
||||
}
|
||||
|
||||
if (this.activeResult) {
|
||||
this.activeResult.node.focus(this.activeResult.elem);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel any running onDelayedSearch.
|
||||
*/
|
||||
JSONEditor.SearchBox.prototype.clearDelay = function() {
|
||||
if (this.timeout != undefined) {
|
||||
clearTimeout(this.timeout);
|
||||
delete this.timeout;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Start a timer to execute a search after a short delay.
|
||||
* Used for reducing the number of searches while typing.
|
||||
* @param {Event} event
|
||||
*/
|
||||
JSONEditor.SearchBox.prototype.onDelayedSearch = function (event) {
|
||||
// execute the search after a short delay (reduces the number of
|
||||
// search actions while typing in the search text box)
|
||||
this.clearDelay();
|
||||
var searchBox = this;
|
||||
this.timeout = setTimeout(function (event) {
|
||||
searchBox.onSearch(event);
|
||||
},
|
||||
this.delay);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle onSearch event
|
||||
* @param {Event} event
|
||||
* @param {boolean} [forceSearch] If true, search will be executed again even
|
||||
* when the search text is not changed.
|
||||
* Default is false.
|
||||
*/
|
||||
JSONEditor.SearchBox.prototype.onSearch = function (event, forceSearch) {
|
||||
this.clearDelay();
|
||||
|
||||
var value = this.dom.search.value;
|
||||
var text = (value.length > 0) ? value : undefined;
|
||||
if (text != this.lastText || forceSearch) {
|
||||
// only search again when changed
|
||||
this.lastText = text;
|
||||
this.results = this.editor.search(text);
|
||||
this.setActiveResult(undefined);
|
||||
|
||||
// display search results
|
||||
if (text != undefined) {
|
||||
var resultCount = this.results.length;
|
||||
switch (resultCount) {
|
||||
case 0: this.dom.results.innerHTML = 'no results'; break;
|
||||
case 1: this.dom.results.innerHTML = '1 result'; break;
|
||||
default: this.dom.results.innerHTML = resultCount + ' results'; break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.dom.results.innerHTML = '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle onKeyDown event in the input box
|
||||
* @param {Event} event
|
||||
*/
|
||||
JSONEditor.SearchBox.prototype.onKeyDown = function (event) {
|
||||
event = event || window.event;
|
||||
var keynum = event.which || event.keyCode;
|
||||
if (keynum == 27) { // ESC
|
||||
this.dom.search.value = ''; // clear search
|
||||
this.onSearch(event);
|
||||
JSONEditor.util.preventDefault(event);
|
||||
JSONEditor.util.stopPropagation(event);
|
||||
}
|
||||
else if (keynum == 13) { // Enter
|
||||
if (event.ctrlKey) {
|
||||
// force to search again
|
||||
this.onSearch(event, true);
|
||||
}
|
||||
else if (event.shiftKey) {
|
||||
// move to the previous search result
|
||||
this.previous();
|
||||
}
|
||||
else {
|
||||
// move to the next search result
|
||||
this.next();
|
||||
}
|
||||
JSONEditor.util.preventDefault(event);
|
||||
JSONEditor.util.stopPropagation(event);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle onKeyUp event in the input box
|
||||
* @param {Event} event
|
||||
*/
|
||||
JSONEditor.SearchBox.prototype.onKeyUp = function (event) {
|
||||
event = event || window.event;
|
||||
var keynum = event.which || event.keyCode;
|
||||
if (keynum != 27 && keynum != 13) { // !show and !Enter
|
||||
this.onDelayedSearch(event); // For IE 8
|
||||
}
|
||||
};
|
|
@ -0,0 +1,380 @@
|
|||
/**
|
||||
* @license
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*
|
||||
* Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
*/
|
||||
|
||||
// create namespace for util methods
|
||||
JSONEditor.util = {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the absolute left value of a DOM element
|
||||
* @param {Element} elem A dom element, for example a div
|
||||
* @return {Number} left The absolute left position of this element
|
||||
* in the browser page.
|
||||
*/
|
||||
JSONEditor.util.getAbsoluteLeft = function (elem) {
|
||||
var left = elem.offsetLeft;
|
||||
var body = document.body;
|
||||
var e = elem.offsetParent;
|
||||
while (e != null && elem != body) {
|
||||
left += e.offsetLeft;
|
||||
left -= e.scrollLeft;
|
||||
e = e.offsetParent;
|
||||
}
|
||||
return left;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the absolute top value of a DOM element
|
||||
* @param {Element} elem A dom element, for example a div
|
||||
* @return {Number} top The absolute top position of this element
|
||||
* in the browser page.
|
||||
*/
|
||||
JSONEditor.util.getAbsoluteTop = function (elem) {
|
||||
var top = elem.offsetTop;
|
||||
var body = document.body;
|
||||
var e = elem.offsetParent;
|
||||
while (e != null && e != body) {
|
||||
top += e.offsetTop;
|
||||
top -= e.scrollTop;
|
||||
e = e.offsetParent;
|
||||
}
|
||||
return top;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the absolute, vertical mouse position from an event.
|
||||
* @param {Event} event
|
||||
* @return {Number} mouseY
|
||||
*/
|
||||
JSONEditor.util.getMouseY = function (event) {
|
||||
var mouseY;
|
||||
if ('pageY' in event) {
|
||||
mouseY = event.pageY;
|
||||
}
|
||||
else {
|
||||
// for IE8 and older
|
||||
mouseY = (event.clientY + document.documentElement.scrollTop);
|
||||
}
|
||||
|
||||
return mouseY;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the absolute, horizontal mouse position from an event.
|
||||
* @param {Event} event
|
||||
* @return {Number} mouseX
|
||||
*/
|
||||
JSONEditor.util.getMouseX = function (event) {
|
||||
var mouseX;
|
||||
if ('pageX' in event) {
|
||||
mouseX = event.pageX;
|
||||
}
|
||||
else {
|
||||
// for IE8 and older
|
||||
mouseX = (event.clientX + document.documentElement.scrollLeft);
|
||||
}
|
||||
|
||||
return mouseX;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the window height
|
||||
* @return {Number} windowHeight
|
||||
*/
|
||||
JSONEditor.util.getWindowHeight = function () {
|
||||
if ('innerHeight' in window) {
|
||||
return window.innerHeight;
|
||||
}
|
||||
else {
|
||||
// for IE8 and older
|
||||
return Math.max(document.body.clientHeight,
|
||||
document.documentElement.clientHeight);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* add a className to the given elements style
|
||||
* @param {Element} elem
|
||||
* @param {String} className
|
||||
*/
|
||||
JSONEditor.util.addClassName = function(elem, className) {
|
||||
var classes = elem.className.split(' ');
|
||||
if (classes.indexOf(className) == -1) {
|
||||
classes.push(className); // add the class to the array
|
||||
elem.className = classes.join(' ');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* add a className to the given elements style
|
||||
* @param {Element} elem
|
||||
* @param {String} className
|
||||
*/
|
||||
JSONEditor.util.removeClassName = function(elem, className) {
|
||||
var classes = elem.className.split(' ');
|
||||
var index = classes.indexOf(className);
|
||||
if (index != -1) {
|
||||
classes.splice(index, 1); // remove the class from the array
|
||||
elem.className = classes.join(' ');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Strip the formatting from the contents of a div
|
||||
* the formatting from the div itself is not stripped, only from its childs.
|
||||
* @param {Element} divElement
|
||||
*/
|
||||
JSONEditor.util.stripFormatting = function (divElement) {
|
||||
var childs = divElement.childNodes;
|
||||
for (var i = 0, iMax = childs.length; i < iMax; i++) {
|
||||
var child = childs[i];
|
||||
|
||||
// remove the style
|
||||
if (child.style) {
|
||||
// TODO: test if child.attributes does contain style
|
||||
child.removeAttribute('style');
|
||||
}
|
||||
|
||||
// remove all attributes
|
||||
var attributes = child.attributes;
|
||||
if (attributes) {
|
||||
for (var j = attributes.length - 1; j >= 0; j--) {
|
||||
var attribute = attributes[j];
|
||||
if (attribute.specified == true) {
|
||||
child.removeAttribute(attribute.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// recursively strip childs
|
||||
JSONEditor.util.stripFormatting(child);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set focus to the end of an editable div
|
||||
* code from Nico Burns
|
||||
* http://stackoverflow.com/users/140293/nico-burns
|
||||
* http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity
|
||||
* @param {Element} contentEditableElement
|
||||
*/
|
||||
JSONEditor.util.setEndOfContentEditable = function (contentEditableElement) {
|
||||
var range, selection;
|
||||
if(document.createRange) {//Firefox, Chrome, Opera, Safari, IE 9+
|
||||
range = document.createRange();//Create a range (a range is a like the selection but invisible)
|
||||
range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range
|
||||
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
|
||||
selection = window.getSelection();//get the selection object (allows you to change selection)
|
||||
selection.removeAllRanges();//remove any selections already made
|
||||
selection.addRange(range);//make the range you have just created the visible selection
|
||||
}
|
||||
else if(document.selection) {//IE 8 and lower
|
||||
range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible)
|
||||
range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range
|
||||
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
|
||||
range.select();//Select the range (make it the visible selection
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the inner text of an HTML element (for example a div element)
|
||||
* @param {Element} element
|
||||
* @param {Object} [buffer]
|
||||
* @return {String} innerText
|
||||
*/
|
||||
JSONEditor.util.getInnerText = function (element, buffer) {
|
||||
var first = (buffer == undefined);
|
||||
if (first) {
|
||||
buffer = {
|
||||
'text': '',
|
||||
'flush': function () {
|
||||
var text = this.text;
|
||||
this.text = '';
|
||||
return text;
|
||||
},
|
||||
'set': function (text) {
|
||||
this.text = text;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// text node
|
||||
if (element.nodeValue) {
|
||||
return buffer.flush() + element.nodeValue;
|
||||
}
|
||||
|
||||
// divs or other HTML elements
|
||||
if (element.hasChildNodes()) {
|
||||
var childNodes = element.childNodes;
|
||||
var innerText = '';
|
||||
|
||||
for (var i = 0, iMax = childNodes.length; i < iMax; i++) {
|
||||
var child = childNodes[i];
|
||||
|
||||
if (child.nodeName == 'DIV' || child.nodeName == 'P') {
|
||||
var prevChild = childNodes[i - 1];
|
||||
var prevName = prevChild ? prevChild.nodeName : undefined;
|
||||
if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') {
|
||||
innerText += '\n';
|
||||
buffer.flush();
|
||||
}
|
||||
innerText += JSONEditor.util.getInnerText(child, buffer);
|
||||
buffer.set('\n');
|
||||
}
|
||||
else if (child.nodeName == 'BR') {
|
||||
innerText += buffer.flush();
|
||||
buffer.set('\n');
|
||||
}
|
||||
else {
|
||||
innerText += JSONEditor.util.getInnerText(child, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return innerText;
|
||||
}
|
||||
else {
|
||||
if (element.nodeName == 'P' && JSONEditor.util.getInternetExplorerVersion() != -1) {
|
||||
// On Internet Explorer, a <p> with hasChildNodes()==false is
|
||||
// rendered with a new line. Note that a <p> with
|
||||
// hasChildNodes()==true is rendered without a new line
|
||||
// Other browsers always ensure there is a <br> inside the <p>,
|
||||
// and if not, the <p> does not render a new line
|
||||
return buffer.flush();
|
||||
}
|
||||
}
|
||||
|
||||
// br or unknown
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the version of Internet Explorer or a -1
|
||||
* (indicating the use of another browser).
|
||||
* Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx
|
||||
* @return {Number} Internet Explorer version, or -1 in case of an other browser
|
||||
*/
|
||||
JSONEditor.util._ieVersion = undefined;
|
||||
JSONEditor.util.getInternetExplorerVersion = function() {
|
||||
if (JSONEditor.util._ieVersion == undefined) {
|
||||
var rv = -1; // Return value assumes failure.
|
||||
if (navigator.appName == 'Microsoft Internet Explorer')
|
||||
{
|
||||
var ua = navigator.userAgent;
|
||||
var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
|
||||
if (re.exec(ua) != null) {
|
||||
rv = parseFloat( RegExp.$1 );
|
||||
}
|
||||
}
|
||||
|
||||
JSONEditor.util._ieVersion = rv;
|
||||
}
|
||||
|
||||
return JSONEditor.util._ieVersion;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add and event listener. Works for all browsers
|
||||
* @param {Element} element An html element
|
||||
* @param {string} action The action, for example "click",
|
||||
* without the prefix "on"
|
||||
* @param {function} listener The callback function to be executed
|
||||
* @param {boolean} [useCapture] false by default
|
||||
* @return {function} the created event listener
|
||||
*/
|
||||
JSONEditor.util.addEventListener = function (element, action, listener, useCapture) {
|
||||
if (element.addEventListener) {
|
||||
if (useCapture === undefined)
|
||||
useCapture = false;
|
||||
|
||||
if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) {
|
||||
action = "DOMMouseScroll"; // For Firefox
|
||||
}
|
||||
|
||||
element.addEventListener(action, listener, useCapture);
|
||||
return listener;
|
||||
} else {
|
||||
// IE browsers
|
||||
var f = function () {
|
||||
return listener.call(element, window.event);
|
||||
};
|
||||
element.attachEvent("on" + action, f);
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove an event listener from an element
|
||||
* @param {Element} element An html dom element
|
||||
* @param {string} action The name of the event, for example "mousedown"
|
||||
* @param {function} listener The listener function
|
||||
* @param {boolean} [useCapture] false by default
|
||||
*/
|
||||
JSONEditor.util.removeEventListener = function(element, action, listener, useCapture) {
|
||||
if (element.removeEventListener) {
|
||||
// non-IE browsers
|
||||
if (useCapture === undefined)
|
||||
useCapture = false;
|
||||
|
||||
if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) {
|
||||
action = "DOMMouseScroll"; // For Firefox
|
||||
}
|
||||
|
||||
element.removeEventListener(action, listener, useCapture);
|
||||
} else {
|
||||
// IE browsers
|
||||
element.detachEvent("on" + action, listener);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stop event propagation
|
||||
* @param {Event} event
|
||||
*/
|
||||
JSONEditor.util.stopPropagation = function (event) {
|
||||
if (!event) {
|
||||
event = window.event;
|
||||
}
|
||||
|
||||
if (event.stopPropagation) {
|
||||
event.stopPropagation(); // non-IE browsers
|
||||
}
|
||||
else {
|
||||
event.cancelBubble = true; // IE browsers
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cancels the event if it is cancelable, without stopping further propagation of the event.
|
||||
* @param {Event} event
|
||||
*/
|
||||
JSONEditor.util.preventDefault = function (event) {
|
||||
if (!event) {
|
||||
event = window.event;
|
||||
}
|
||||
|
||||
if (event.preventDefault) {
|
||||
event.preventDefault(); // non-IE browsers
|
||||
}
|
||||
else {
|
||||
event.returnValue = false; // IE browsers
|
||||
}
|
||||
};
|
|
@ -1,585 +0,0 @@
|
|||
|
||||
.jsoneditor-field, .jsoneditor-value, .jsoneditor-field-readonly, .jsoneditor-readonly {
|
||||
border: 1px solid transparent;
|
||||
min-height: 16px;
|
||||
min-width: 24px;
|
||||
padding: 2px;
|
||||
margin: 1px;
|
||||
outline: none;
|
||||
word-wrap: break-word;
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* adjust margin of p elements inside editable divs, needed for Opera, IE */
|
||||
.jsoneditor-field p, .jsoneditor-value p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.jsoneditor-value {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.jsoneditor-empty {
|
||||
background-color: #E5E5E5;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsoneditor-separator {
|
||||
padding: 3px 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.jsoneditor-value:focus, .jsoneditor-field:focus,
|
||||
.jsoneditor-value:hover, .jsoneditor-field:hover,
|
||||
.jsoneditor-search-highlight {
|
||||
background-color: #FFFFAB;
|
||||
border: 1px solid yellow;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsoneditor-search-highlight-active,
|
||||
.jsoneditor-search-highlight-active:focus,
|
||||
.jsoneditor-search-highlight-active:hover {
|
||||
background-color: #ffee00;
|
||||
border: 1px solid #ffc700;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.jsoneditor-field-readonly:hover {
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.jsoneditor-readonly {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
button.jsoneditor-collapsed, button.jsoneditor-expanded,
|
||||
button.jsoneditor-invisible, button.jsoneditor-dragarea,
|
||||
button.jsoneditor-contextmenu, button.jsoneditor-append {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
background-image: url('img/jsoneditor-icons.png');
|
||||
}
|
||||
|
||||
/* TODO: no global settings
|
||||
button:disabled {
|
||||
color: #808080;
|
||||
}
|
||||
*/
|
||||
|
||||
td.jsoneditor-nochilds {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
button.jsoneditor-collapsed {
|
||||
background-position: 0 -48px;
|
||||
}
|
||||
|
||||
button.jsoneditor-expanded {
|
||||
background-position: 0 -72px;
|
||||
}
|
||||
|
||||
.jsoneditor-contextmenu {
|
||||
position: relative;
|
||||
background-position: -48px -72px;
|
||||
}
|
||||
|
||||
.jsoneditor-contextmenu:hover, .jsoneditor-contextmenu:focus {
|
||||
background-position: -48px -48px;
|
||||
}
|
||||
|
||||
button.jsoneditor-invisible {
|
||||
visibility: hidden;
|
||||
background: none;
|
||||
}
|
||||
|
||||
button.jsoneditor-collapsed, button.jsoneditor-expanded,
|
||||
button.jsoneditor-invisible {
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.jsoneditor-frame {
|
||||
color: #1A1A1A;
|
||||
border: 1px solid #97B0F8;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.jsoneditor-table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.jsoneditor-content-outer, div.jsonformatter-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: -35px 0 0 0;
|
||||
padding: 35px 0 0 0;
|
||||
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.jsoneditor-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
textarea.jsonformatter-textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
border: none;
|
||||
background-color: white;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
tr.jsoneditor-tr-highlight {
|
||||
background-color: #FFFFAB;
|
||||
}
|
||||
|
||||
button.jsoneditor-dragarea {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
/*
|
||||
margin: 3px 0;
|
||||
background: url('img/dots_gray.gif') top center;
|
||||
background-repeat: repeat-y;
|
||||
*/
|
||||
background: url('img/jsoneditor-icons.png') -72px -72px;
|
||||
|
||||
display: block;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
button.jsoneditor-dragarea:hover, .jsoneditor-dragarea:focus {
|
||||
background-position: -72px -48px;
|
||||
}
|
||||
|
||||
/* ___________________________ COMPONENT TOP MENU ___________________________ */
|
||||
|
||||
|
||||
div.jsoneditor-menu {
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
color: #1A1A1A;
|
||||
background-color: #D5DDF6;
|
||||
border-bottom: 1px solid #97B0F8;
|
||||
}
|
||||
|
||||
button.jsoneditor-menu {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #aec0f8;
|
||||
background: #e3eaf6 url('img/jsoneditor-icons.png');
|
||||
}
|
||||
|
||||
button.jsoneditor-menu:hover {
|
||||
background-color: #f0f2f5;
|
||||
}
|
||||
button.jsoneditor-menu:active {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
button.jsoneditor-menu:disabled {
|
||||
background-color: #e3eaf6;
|
||||
}
|
||||
|
||||
button.jsoneditor-collapse-all {
|
||||
background-position: 0 -96px;
|
||||
}
|
||||
button.jsoneditor-expand-all {
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
button.jsoneditor-undo {
|
||||
background-position: -24px -96px;
|
||||
}
|
||||
button.jsoneditor-undo:disabled {
|
||||
background-position: -24px -120px;
|
||||
}
|
||||
button.jsoneditor-redo {
|
||||
background-position: -48px -96px;
|
||||
}
|
||||
button.jsoneditor-redo:disabled {
|
||||
background-position: -48px -120px;
|
||||
}
|
||||
/* TODO: css for button:disabled is not supported by IE8 */
|
||||
button.jsoneditor-compact {
|
||||
background-position: -72px -96px;
|
||||
}
|
||||
button.jsoneditor-format {
|
||||
background-position: -72px -120px;
|
||||
}
|
||||
|
||||
/* TODO: do not change global tr, th, td */
|
||||
tr, th, td {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
td.jsoneditor-td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td.jsoneditor-td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
td.jsoneditor-td-edit {
|
||||
background-color: #F5F5F5;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
td.jsoneditor-td-tree {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td.jsoneditor-droparea {
|
||||
height: 24px;
|
||||
|
||||
border-top: 1px dashed gray;
|
||||
border-bottom: 1px dashed gray;
|
||||
background-color: #FFFF80;
|
||||
}
|
||||
|
||||
.jsoneditor-field, .jsoneditor-value, .jsoneditor-td, .jsoneditor-th,
|
||||
.jsoneditor-type, .jsonformatter-textarea {
|
||||
font-family: droid sans mono, monospace, courier new, courier, sans-serif;
|
||||
font-size: 10pt;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu button,
|
||||
input.jsoneditor-search, div.jsoneditor-search-results {
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.jsoneditor-hidden-focus {
|
||||
position: absolute;
|
||||
left: -1000px;
|
||||
top: -1000px;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* _______________________________ SEARCH BAR _______________________________ */
|
||||
|
||||
table.jsoneditor-search {
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
table.jsoneditor-search-input {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
div.jsoneditor-search {
|
||||
border: 1px solid #97B0F8;
|
||||
background-color: white;
|
||||
padding: 0 2px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input.jsoneditor-search {
|
||||
width: 120px;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
div.jsoneditor-search-results {
|
||||
color: #4d4d4d;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
button.jsoneditor-search-refresh, button.jsoneditor-search-next,
|
||||
button.jsoneditor-search-previous {
|
||||
width: 16px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: url('img/jsoneditor-icons.png');
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
button.jsoneditor-search-refresh {
|
||||
width: 18px;
|
||||
background-position: -99px -73px;
|
||||
}
|
||||
|
||||
button.jsoneditor-search-next {
|
||||
cursor: pointer;
|
||||
background-position: -124px -73px;
|
||||
}
|
||||
button.jsoneditor-search-next:hover {
|
||||
background-position: -124px -49px;
|
||||
}
|
||||
|
||||
button.jsoneditor-search-previous {
|
||||
cursor: pointer;
|
||||
background-position: -148px -73px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
button.jsoneditor-search-previous:hover {
|
||||
background-position: -148px -49px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ______________________________ CONTEXT MENU ______________________________ */
|
||||
|
||||
div.jsoneditor-contextmenu {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul {
|
||||
position: relative;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 124px;
|
||||
|
||||
background: white;
|
||||
border: 1px solid #d3d3d3;
|
||||
box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
|
||||
|
||||
z-index: 1;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 124px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: #4d4d4d;
|
||||
background: transparent;
|
||||
|
||||
line-height: 24px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Fix button padding in firefox */
|
||||
div.jsoneditor-contextmenu ul li button::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button:hover {
|
||||
color: #1a1a1a;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button.default {
|
||||
width: 92px;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button.expand {
|
||||
float: right;
|
||||
width: 32px;
|
||||
height: 24px;
|
||||
border-left: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu div.icon {
|
||||
float: left;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-image: url('img/jsoneditor-icons.png');
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button div.expand {
|
||||
float: right;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0 4px 0 0;
|
||||
background: url('img/jsoneditor-icons.png') 0 -72px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li button:hover div.expand,
|
||||
div.jsoneditor-contextmenu ul li.selected div.expand,
|
||||
div.jsoneditor-contextmenu ul li button.expand:hover div.expand {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu .separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
padding-top: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
button.jsoneditor-remove > .icon {
|
||||
background-position: -24px -24px;
|
||||
}
|
||||
button.jsoneditor-remove:hover > .icon {
|
||||
background-position: -24px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-append > .icon {
|
||||
background-position: 0 -24px;
|
||||
}
|
||||
button.jsoneditor-append:hover > .icon {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-insert > .icon {
|
||||
background-position: 0 -24px;
|
||||
}
|
||||
button.jsoneditor-insert:hover > .icon {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-insert-above > .icon {
|
||||
background-position: -24px -24px;
|
||||
}
|
||||
button.jsoneditor-insert-above:hover > .icon {
|
||||
background-position: -24px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-insert-below > .icon {
|
||||
background-position: -48px -24px;
|
||||
}
|
||||
button.jsoneditor-insert-below:hover > .icon {
|
||||
background-position: -48px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-duplicate > .icon {
|
||||
background-position: -48px -24px;
|
||||
}
|
||||
button.jsoneditor-duplicate:hover > .icon {
|
||||
background-position: -48px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-sort-asc > .icon {
|
||||
background-position: -168px -24px;
|
||||
}
|
||||
button.jsoneditor-sort-asc:hover > .icon {
|
||||
background-position: -168px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-sort-desc > .icon {
|
||||
background-position: -192px -24px;
|
||||
}
|
||||
button.jsoneditor-sort-desc:hover > .icon {
|
||||
background-position: -192px 0;
|
||||
}
|
||||
|
||||
/* ____________________________ CONTEXT SUB MENU ____________________________ */
|
||||
|
||||
|
||||
div.jsoneditor-contextmenu ul li ul li .selected {
|
||||
background-color: #D5DDF6;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li ul {
|
||||
display: none;
|
||||
position: relative;
|
||||
left: -10px;
|
||||
top: 0;
|
||||
|
||||
border: none;
|
||||
box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5);
|
||||
padding: 0 10px;
|
||||
|
||||
/* TODO: transition is not supported on IE8-9 */
|
||||
-webkit-transition: all 0.3s ease-out;
|
||||
-moz-transition: all 0.3s ease-out;
|
||||
-o-transition: all 0.3s ease-out;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li.selected ul {
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li ul li button {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li ul li button:hover {
|
||||
background-color: #f5f5f5;
|
||||
|
||||
}
|
||||
|
||||
button.jsoneditor-type-string > .icon {
|
||||
background-position: -144px -24px;
|
||||
}
|
||||
button.jsoneditor-type-string:hover > .icon,
|
||||
button.jsoneditor-type-string.selected > .icon{
|
||||
background-position: -144px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-type-auto > .icon {
|
||||
background-position: -120px -24px;
|
||||
}
|
||||
button.jsoneditor-type-auto:hover > .icon,
|
||||
button.jsoneditor-type-auto.selected > .icon {
|
||||
background-position: -120px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-type-object > .icon {
|
||||
background-position: -72px -24px;
|
||||
}
|
||||
button.jsoneditor-type-object:hover > .icon,
|
||||
button.jsoneditor-type-object.selected > .icon{
|
||||
background-position: -72px 0;
|
||||
}
|
||||
|
||||
button.jsoneditor-type-array > .icon {
|
||||
background-position: -96px -24px;
|
||||
}
|
||||
button.jsoneditor-type-array:hover > .icon,
|
||||
button.jsoneditor-type-array.selected > .icon{
|
||||
background-position: -96px 0;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: drastically cleanup the css, improve/simplify naming and cascading */
|
File diff suppressed because it is too large
Load Diff
|
@ -10,8 +10,8 @@
|
|||
<link rel="shortcut icon" href="../app/web/favicon.ico">
|
||||
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../jsoneditor/jsoneditor.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../jsoneditor/jsoneditor.css">
|
||||
<script type="text/javascript" src="../jsoneditor/js/jsoneditor.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../jsoneditor/css/jsoneditor.css">
|
||||
|
||||
<style type="text/css">
|
||||
body, html {
|
||||
|
|
Loading…
Reference in New Issue