diff --git a/dist/jsoneditor.css b/dist/jsoneditor.css
index 95190c5..0eaf1d8 100644
--- a/dist/jsoneditor.css
+++ b/dist/jsoneditor.css
@@ -1,29 +1,35 @@
-/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */
-
-div.jsoneditor .jsoneditor-search input {
+.jsoneditor .jsoneditor-search input {
height: auto;
border: inherit;
+ border: none;
+ box-shadow: none;
}
-div.jsoneditor .jsoneditor-search input:focus {
- border: none !important;
- box-shadow: none !important;
-}
-
-div.jsoneditor table {
+.jsoneditor table {
border-collapse: collapse;
width: auto;
}
-div.jsoneditor td,
-div.jsoneditor th {
+.jsoneditor td,
+.jsoneditor th {
padding: 0;
display: table-cell;
text-align: left;
vertical-align: inherit;
border-radius: inherit;
}
-
+.jsoneditor {
+ color: #1a1a1a;
+ border: thin solid #3883fa;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ height: 100%;
+ position: relative;
+ padding: 0;
+ line-height: 100%;
+}
div.jsoneditor-field,
div.jsoneditor-value,
@@ -38,8 +44,6 @@ div.jsoneditor-default {
float: left;
}
-/* adjust margin of p elements inside editable divs, needed for Opera, IE */
-
div.jsoneditor-field p,
div.jsoneditor-value p {
margin: 0;
@@ -49,6 +53,30 @@ div.jsoneditor-value {
word-break: break-word;
}
+div.jsoneditor-value.jsoneditor-empty::after {
+ content: "value";
+}
+
+div.jsoneditor-value.jsoneditor-string {
+ color: #006000;
+}
+
+div.jsoneditor-value.jsoneditor-number {
+ color: #ee422e;
+}
+
+div.jsoneditor-value.jsoneditor-boolean {
+ color: #ff8c00;
+}
+
+div.jsoneditor-value.jsoneditor-null {
+ color: #004ed0;
+}
+
+div.jsoneditor-value.jsoneditor-invalid {
+ color: #000000;
+}
+
div.jsoneditor-readonly {
min-width: 16px;
color: #808080;
@@ -60,36 +88,12 @@ div.jsoneditor-empty {
border-radius: 2px;
}
-div.jsoneditor-field.jsoneditor-empty::after,
-div.jsoneditor-value.jsoneditor-empty::after {
- pointer-events: none;
- color: #d3d3d3;
- font-size: 8pt;
-}
-
div.jsoneditor-field.jsoneditor-empty::after {
content: "field";
}
-div.jsoneditor-value.jsoneditor-empty::after {
- content: "value";
-}
-
-div.jsoneditor-value.jsoneditor-url,
-a.jsoneditor-value.jsoneditor-url {
- color: green;
- text-decoration: underline;
-}
-
-a.jsoneditor-value.jsoneditor-url {
- display: inline-block;
- padding: 2px;
- margin: 2px;
-}
-
-a.jsoneditor-value.jsoneditor-url:hover,
-a.jsoneditor-value.jsoneditor-url:focus {
- color: #ee422e;
+div.jsoneditor td {
+ vertical-align: top;
}
div.jsoneditor td.jsoneditor-separator {
@@ -98,51 +102,37 @@ div.jsoneditor td.jsoneditor-separator {
color: #808080;
}
-div.jsoneditor-field[contenteditable=true]:focus,
-div.jsoneditor-field[contenteditable=true]:hover,
-div.jsoneditor-value[contenteditable=true]:focus,
-div.jsoneditor-value[contenteditable=true]:hover,
-div.jsoneditor-field.jsoneditor-highlight,
-div.jsoneditor-value.jsoneditor-highlight {
- background-color: #FFFFAB;
- border: 1px solid yellow;
- border-radius: 2px;
+div.jsoneditor td.jsoneditor-tree {
+ vertical-align: top;
}
-div.jsoneditor-field.jsoneditor-highlight-active,
-div.jsoneditor-field.jsoneditor-highlight-active:focus,
-div.jsoneditor-field.jsoneditor-highlight-active:hover,
-div.jsoneditor-value.jsoneditor-highlight-active,
-div.jsoneditor-value.jsoneditor-highlight-active:focus,
-div.jsoneditor-value.jsoneditor-highlight-active:hover {
- background-color: #ffee00;
- border: 1px solid #ffc700;
- border-radius: 2px;
+div.jsoneditor div.jsoneditor-anchor .picker_wrapper.popup.popup_bottom {
+ top: 28px;
+ left: -10px;
}
-div.jsoneditor-value.jsoneditor-string {
- color: #006000;
+div.jsoneditor.busy pre.jsoneditor-preview {
+ background: #f5f5f5;
+ color: #808080;
}
-div.jsoneditor-value.jsoneditor-object,
-div.jsoneditor-value.jsoneditor-array {
- min-width: 16px;
+div.jsoneditor.busy div.jsoneditor-busy {
+ display: inherit;
}
-div.jsoneditor-value.jsoneditor-number {
- color: #ee422e;
+div.jsoneditor code.jsoneditor-preview {
+ background: none;
}
-div.jsoneditor-value.jsoneditor-boolean {
- color: #ff8c00;
-}
-
-div.jsoneditor-value.jsoneditor-null {
- color: #004ED0;
-}
-
-div.jsoneditor-value.jsoneditor-invalid {
- color: #000000;
+div.jsoneditor.jsoneditor-mode-preview pre.jsoneditor-preview {
+ width: 100%;
+ height: 100%;
+ box-sizing: border-box;
+ overflow: auto;
+ padding: 2px;
+ margin: 0;
+ white-space: pre-wrap;
+ word-break: break-all;
}
div.jsoneditor-default {
@@ -150,6 +140,13 @@ div.jsoneditor-default {
padding-left: 10px;
}
+div.jsoneditor-tree {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ overflow: auto;
+}
+
div.jsoneditor-tree button.jsoneditor-button {
width: 24px;
height: 24px;
@@ -160,9 +157,9 @@ div.jsoneditor-tree button.jsoneditor-button {
background: transparent url("img/jsoneditor-icons.svg");
}
-div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree,
-div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree {
- cursor: pointer;
+div.jsoneditor-tree button.jsoneditor-button:focus {
+ background-color: #f5f5f5;
+ outline: #e5e5e5 solid 1px;
}
div.jsoneditor-tree button.jsoneditor-collapsed {
@@ -177,31 +174,20 @@ div.jsoneditor-tree button.jsoneditor-contextmenu {
background-position: -48px -72px;
}
-div.jsoneditor-tree button.jsoneditor-contextmenu:hover,
-div.jsoneditor-tree button.jsoneditor-contextmenu:focus,
-div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected,
-tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
- background-position: -48px -48px;
+div.jsoneditor-tree button.jsoneditor-invisible {
+ visibility: hidden;
+ background: none;
+}
+
+div.jsoneditor-tree button.jsoneditor-dragarea {
+ background: url("img/jsoneditor-icons.svg") -72px -72px;
+ cursor: move;
}
div.jsoneditor-tree *:focus {
outline: none;
}
-div.jsoneditor-tree button.jsoneditor-button:focus {
- /* TODO: nice outline for buttons with focus
- outline: #97B0F8 solid 2px;
- box-shadow: 0 0 8px #97B0F8;
- */
- background-color: #f5f5f5;
- outline: #e5e5e5 solid 1px;
-}
-
-div.jsoneditor-tree button.jsoneditor-invisible {
- visibility: hidden;
- background: none;
-}
-
div.jsoneditor-tree div.jsoneditor-show-more {
display: inline-block;
padding: 3px 4px;
@@ -218,11 +204,6 @@ div.jsoneditor-tree div.jsoneditor-show-more a {
color: #808080;
}
-div.jsoneditor-tree div.jsoneditor-show-more a:hover,
-div.jsoneditor-tree div.jsoneditor-show-more a:focus {
- color: #ee422e;
-}
-
div.jsoneditor-tree div.jsoneditor-color {
display: inline-block;
width: 12px;
@@ -232,14 +213,9 @@ div.jsoneditor-tree div.jsoneditor-color {
cursor: pointer;
}
-div.jsoneditor div.jsoneditor-anchor .picker_wrapper.popup.popup_bottom {
- top: 28px;
- left: -10px;
-}
-
div.jsoneditor-tree div.jsoneditor-date {
background: #a1a1a1;
- color: white;
+ color: #ffffff;
font-family: arial, sans-serif;
border-radius: 3px;
display: inline-block;
@@ -247,26 +223,20 @@ div.jsoneditor-tree div.jsoneditor-date {
margin: 0 3px;
}
-div.jsoneditor {
- color: #1A1A1A;
- border: thin solid #3883fa;
- /* we use thin and not 1px to work around an issue in Chrome/IE, see #637 */
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
- width: 100%;
- height: 100%;
- position: relative;
- padding: 0;
- line-height: 100%;
-}
-
div.jsoneditor-tree table.jsoneditor-tree {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
+div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
+ width: 24px;
+ height: 24px;
+ padding: 0;
+ margin: 0 4px 0 0;
+ background: url("img/jsoneditor-icons.svg") -168px -48px;
+}
+
div.jsoneditor-outer {
position: static;
width: 100%;
@@ -283,6 +253,11 @@ div.jsoneditor-outer.has-nav-bar {
padding-top: 26px;
}
+div.jsoneditor-outer.has-nav-bar.has-main-menu-bar {
+ margin-top: -61px;
+ padding-top: 61px;
+}
+
div.jsoneditor-outer.has-status-bar {
margin-bottom: -26px;
padding-bottom: 26px;
@@ -293,33 +268,6 @@ div.jsoneditor-outer.has-main-menu-bar {
padding-top: 35px;
}
-div.jsoneditor-outer.has-nav-bar.has-main-menu-bar {
- margin-top: -61px;
- padding-top: 61px;
-}
-
-
-
-div.jsoneditor.busy pre.jsoneditor-preview {
- background: #f5f5f5;
- color: #808080;
-}
-
-div.jsoneditor code.jsoneditor-preview {
- background: none;
-}
-
-div.jsoneditor.jsoneditor-mode-preview pre.jsoneditor-preview {
- width: 100%;
- height: 100%;
- box-sizing: border-box;
- overflow: auto;
- padding: 2px;
- margin: 0;
- white-space: pre-wrap;
- word-break: break-all;
-}
-
div.jsoneditor-busy {
position: absolute;
top: 15%;
@@ -331,15 +279,79 @@ div.jsoneditor-busy {
}
div.jsoneditor-busy span {
- background-color: #FFFFAB;
- border: 1px solid yellow;
+ background-color: #ffffab;
+ border: 1px solid #ffee00;
border-radius: 3px;
padding: 5px 15px;
- box-shadow: 0 0 5px rgba(0,0,0,0.4);
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
}
-div.jsoneditor.busy div.jsoneditor-busy {
- display: inherit;
+div.jsoneditor-field.jsoneditor-empty::after,
+div.jsoneditor-value.jsoneditor-empty::after {
+ pointer-events: none;
+ color: #d3d3d3;
+ font-size: 8pt;
+}
+
+div.jsoneditor-value.jsoneditor-url,
+a.jsoneditor-value.jsoneditor-url {
+ color: #006000;
+ text-decoration: underline;
+}
+
+a.jsoneditor-value.jsoneditor-url {
+ display: inline-block;
+ padding: 2px;
+ margin: 2px;
+}
+
+a.jsoneditor-value.jsoneditor-url:hover,
+a.jsoneditor-value.jsoneditor-url:focus {
+ color: #ee422e;
+}
+
+div.jsoneditor-field[contenteditable="true"]:focus,
+div.jsoneditor-field[contenteditable="true"]:hover,
+div.jsoneditor-value[contenteditable="true"]:focus,
+div.jsoneditor-value[contenteditable="true"]:hover,
+div.jsoneditor-field.jsoneditor-highlight,
+div.jsoneditor-value.jsoneditor-highlight {
+ background-color: #ffffab;
+ border: 1px solid #ffee00;
+ border-radius: 2px;
+}
+
+div.jsoneditor-field.jsoneditor-highlight-active,
+div.jsoneditor-field.jsoneditor-highlight-active:focus,
+div.jsoneditor-field.jsoneditor-highlight-active:hover,
+div.jsoneditor-value.jsoneditor-highlight-active,
+div.jsoneditor-value.jsoneditor-highlight-active:focus,
+div.jsoneditor-value.jsoneditor-highlight-active:hover {
+ background-color: #ffee00;
+ border: 1px solid #ffc700;
+ border-radius: 2px;
+}
+
+div.jsoneditor-value.jsoneditor-object,
+div.jsoneditor-value.jsoneditor-array {
+ min-width: 16px;
+}
+
+div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree,
+div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree {
+ cursor: pointer;
+}
+
+div.jsoneditor-tree button.jsoneditor-contextmenu:hover,
+div.jsoneditor-tree button.jsoneditor-contextmenu:focus,
+div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected,
+tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
+ background-position: -48px -48px;
+}
+
+div.jsoneditor-tree div.jsoneditor-show-more a:hover,
+div.jsoneditor-tree div.jsoneditor-show-more a:focus {
+ color: #ee422e;
}
textarea.jsoneditor-text,
@@ -347,13 +359,6 @@ textarea.jsoneditor-text,
min-height: 150px;
}
-div.jsoneditor-tree {
- width: 100%;
- height: 100%;
- position: relative;
- overflow: auto;
-}
-
textarea.jsoneditor-text {
width: 100%;
height: 100%;
@@ -363,7 +368,7 @@ textarea.jsoneditor-text {
box-sizing: border-box;
outline-width: 0;
border: none;
- background-color: white;
+ background-color: #ffffff;
resize: none;
}
@@ -382,11 +387,6 @@ tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
visibility: visible;
}
-div.jsoneditor-tree button.jsoneditor-dragarea {
- background: url("img/jsoneditor-icons.svg") -72px -72px;
- cursor: move;
-}
-
div.jsoneditor-tree button.jsoneditor-dragarea:hover,
div.jsoneditor-tree button.jsoneditor-dragarea:focus,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea {
@@ -400,14 +400,6 @@ div.jsoneditor td {
margin: 0;
}
-div.jsoneditor td {
- vertical-align: top;
-}
-
-div.jsoneditor td.jsoneditor-tree {
- vertical-align: top;
-}
-
div.jsoneditor-field,
div.jsoneditor-value,
div.jsoneditor td,
@@ -417,15 +409,12 @@ div.jsoneditor pre.jsoneditor-preview,
div.jsoneditor .jsoneditor-schema-error {
font-family: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif;
font-size: 10pt;
- color: #1A1A1A;
+ color: #1a1a1a;
}
-/* popover */
-
.jsoneditor-schema-error {
cursor: default;
display: inline-block;
- /*font-family: arial, sans-serif;*/
height: 24px;
line-height: 24px;
position: relative;
@@ -433,24 +422,11 @@ div.jsoneditor .jsoneditor-schema-error {
width: 24px;
}
-div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
- width: 24px;
- height: 24px;
- padding: 0;
- margin: 0 4px 0 0;
- background: url("img/jsoneditor-icons.svg") -168px -48px;
-}
-
-.jsoneditor-text-errors tr.jump-to-line:hover {
- text-decoration: underline;
- cursor: pointer;
-}
-
.jsoneditor-schema-error .jsoneditor-popover {
background-color: #4c4c4c;
border-radius: 3px;
- box-shadow: 0 0 5px rgba(0,0,0,0.4);
- color: #fff;
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
+ color: #ffffff;
display: none;
padding: 7px 10px;
position: absolute;
@@ -463,46 +439,31 @@ div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
left: -98px;
}
-.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below {
- top: 32px;
- left: -98px;
-}
-
-.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left {
- top: -7px;
- right: 32px;
-}
-
-.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right {
- top: -7px;
- left: 32px;
-}
-
-.jsoneditor-schema-error .jsoneditor-popover:before {
- border-right: 7px solid transparent;
- border-left: 7px solid transparent;
- content: '';
- display: block;
- left: 50%;
- margin-left: -7px;
- position: absolute;
-}
-
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before {
border-top: 7px solid #4c4c4c;
bottom: -7px;
}
+.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below {
+ top: 32px;
+ left: -98px;
+}
+
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before {
border-bottom: 7px solid #4c4c4c;
top: -7px;
}
+.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left {
+ top: -7px;
+ right: 32px;
+}
+
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before {
border-left: 7px solid #4c4c4c;
border-top: 7px solid transparent;
border-bottom: 7px solid transparent;
- content: '';
+ content: "";
top: 19px;
right: -14px;
left: inherit;
@@ -511,11 +472,16 @@ div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
position: absolute;
}
+.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right {
+ top: -7px;
+ left: 32px;
+}
+
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before {
border-right: 7px solid #4c4c4c;
border-top: 7px solid transparent;
border-bottom: 7px solid transparent;
- content: '';
+ content: "";
top: 19px;
left: -14px;
margin-left: inherit;
@@ -523,15 +489,28 @@ div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
position: absolute;
}
+.jsoneditor-schema-error .jsoneditor-popover:before {
+ border-right: 7px solid transparent;
+ border-left: 7px solid transparent;
+ content: "";
+ display: block;
+ left: 50%;
+ margin-left: -7px;
+ position: absolute;
+}
+
+.jsoneditor-text-errors tr.jump-to-line:hover {
+ text-decoration: underline;
+ cursor: pointer;
+}
+
.jsoneditor-schema-error:hover .jsoneditor-popover,
.jsoneditor-schema-error:focus .jsoneditor-popover {
display: block;
- -webkit-animation: fade-in .3s linear 1, move-up .3s linear 1;
- -moz-animation: fade-in .3s linear 1, move-up .3s linear 1;
- -ms-animation: fade-in .3s linear 1, move-up .3s linear 1;
+ animation: fade-in 0.3s linear 1, move-up 0.3s linear 1;
}
-@-webkit-keyframes fade-in {
+@keyframes fade-in {
from {
opacity: 0;
}
@@ -541,50 +520,6 @@ div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
}
}
-@-moz-keyframes fade-in {
- from {
- opacity: 0;
- }
-
- to {
- opacity: 1;
- }
-}
-
-@-ms-keyframes fade-in {
- from {
- opacity: 0;
- }
-
- to {
- opacity: 1;
- }
-}
-
-/*@-webkit-keyframes move-up {*/
-
-/*from { bottom: 24px; }*/
-
-/*to { bottom: 32px; }*/
-
-/*}*/
-
-/*@-moz-keyframes move-up {*/
-
-/*from { bottom: 24px; }*/
-
-/*to { bottom: 32px; }*/
-
-/*}*/
-
-/*@-ms-keyframes move-up {*/
-
-/*from { bottom: 24px; }*/
-
-/*to { bottom: 32px; }*/
-
-/*}*/
-
/* JSON schema errors displayed at the bottom of the editor in mode text and code */
.jsoneditor .jsoneditor-validation-errors-container {
@@ -623,7 +558,7 @@ div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
.jsoneditor .jsoneditor-text-errors {
width: 100%;
border-collapse: collapse;
- border-top: 1px solid #ffd700;
+ border-top: 1px solid #ffc700;
}
.jsoneditor .jsoneditor-text-errors td {
@@ -637,7 +572,7 @@ div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
}
.jsoneditor .jsoneditor-text-errors tr {
- background-color: #ffef8b;
+ background-color: #ffffab;
}
.jsoneditor .jsoneditor-text-errors tr.parse-error {
@@ -654,38 +589,18 @@ div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
}
.jsoneditor-text-errors tr .jsoneditor-schema-error {
- background: url("img/jsoneditor-icons.svg") -168px -48px;
+ background: url("img/jsoneditor-icons.svg") -168px -48px;
}
.jsoneditor-text-errors tr.parse-error .jsoneditor-schema-error {
- background: url("img/jsoneditor-icons.svg") -25px 0px;
+ background: url("img/jsoneditor-icons.svg") -25px 0px;
}
.fadein {
- -webkit-animation: fadein .3s;
- animation: fadein .3s;
- -moz-animation: fadein .3s;
- -o-animation: fadein .3s;
-}
-
-@-webkit-keyframes fadein {
- 0% {
- opacity: 0;
- }
-
- 100% {
- opacity: 1;
- }
-}
-
-@-moz-keyframes fadein {
- 0% {
- opacity: 0;
- }
-
- 100% {
- opacity: 1;
- }
+ -webkit-animation: fadein 0.3s;
+ animation: fadein 0.3s;
+ -moz-animation: fadein 0.3s;
+ -o-animation: fadein 0.3s;
}
@keyframes fadein {
@@ -697,42 +612,25 @@ div.jsoneditor-tree .jsoneditor-button.jsoneditor-schema-error {
opacity: 1;
}
}
-
-@-o-keyframes fadein {
- 0% {
- opacity: 0;
- }
-
- 100% {
- opacity: 1;
- }
-}
-/* ContextMenu - main menu */
-
-div.jsoneditor-contextmenu-root {
+.jsoneditor-contextmenu-root {
position: relative;
width: 0;
height: 0;
}
-div.jsoneditor-contextmenu {
+.jsoneditor-contextmenu {
position: absolute;
box-sizing: content-box;
- z-index: 99999;
+ z-index: 99;
}
-div.jsoneditor-contextmenu ul,
-div.jsoneditor-contextmenu li {
- box-sizing: content-box;
- position: relative;
-}
-
-div.jsoneditor-contextmenu ul {
+.jsoneditor-contextmenu .jsoneditor-menu {
position: relative;
left: 0;
top: 0;
width: 128px;
- background: white;
+ height: auto;
+ background: #ffffff;
border: 1px solid #d3d3d3;
box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
list-style: none;
@@ -740,7 +638,7 @@ div.jsoneditor-contextmenu ul {
padding: 0;
}
-div.jsoneditor-contextmenu ul li button {
+.jsoneditor-contextmenu .jsoneditor-menu button {
position: relative;
padding: 0 4px 0 0;
margin: 0;
@@ -756,33 +654,61 @@ div.jsoneditor-contextmenu ul li button {
text-align: left;
}
-/* Fix button padding in firefox */
-
-div.jsoneditor-contextmenu ul li button::-moz-focus-inner {
+.jsoneditor-contextmenu .jsoneditor-menu button::-moz-focus-inner {
padding: 0;
border: 0;
}
-div.jsoneditor-contextmenu ul li button:hover,
-div.jsoneditor-contextmenu ul li button:focus {
- color: #1a1a1a;
- background-color: #f5f5f5;
- outline: none;
-}
-
-div.jsoneditor-contextmenu ul li button.jsoneditor-default {
+.jsoneditor-contextmenu .jsoneditor-menu button.jsoneditor-default {
width: 96px;
- /* 128px - 32px */
}
-div.jsoneditor-contextmenu ul li button.jsoneditor-expand {
+.jsoneditor-contextmenu .jsoneditor-menu button.jsoneditor-expand {
float: right;
width: 32px;
height: 24px;
border-left: 1px solid #e5e5e5;
}
-div.jsoneditor-contextmenu div.jsoneditor-icon {
+.jsoneditor-contextmenu .jsoneditor-menu li {
+ overflow: hidden;
+}
+
+.jsoneditor-contextmenu .jsoneditor-menu 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;
+ -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;
+}
+
+.jsoneditor-contextmenu .jsoneditor-menu li ul .jsoneditor-icon {
+ margin-left: 24px;
+}
+
+.jsoneditor-contextmenu .jsoneditor-menu li ul li button {
+ padding-left: 24px;
+ animation: all ease-in-out 1s;
+}
+
+.jsoneditor-contextmenu .jsoneditor-menu li button .jsoneditor-expand {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 24px;
+ height: 24px;
+ padding: 0;
+ margin: 0 4px 0 0;
+ background: url("img/jsoneditor-icons.svg") 0 -72px;
+}
+
+.jsoneditor-contextmenu .jsoneditor-icon {
position: absolute;
top: 0;
left: 0;
@@ -794,145 +720,105 @@ div.jsoneditor-contextmenu div.jsoneditor-icon {
background-image: url("img/jsoneditor-icons.svg");
}
-div.jsoneditor-contextmenu ul li ul div.jsoneditor-icon {
- margin-left: 24px;
-}
-
-div.jsoneditor-contextmenu div.jsoneditor-text {
+.jsoneditor-contextmenu .jsoneditor-text {
padding: 4px 0 4px 24px;
word-wrap: break-word;
}
-div.jsoneditor-contextmenu div.jsoneditor-text.jsoneditor-right-margin {
+.jsoneditor-contextmenu .jsoneditor-text.jsoneditor-right-margin {
padding-right: 24px;
}
-div.jsoneditor-contextmenu ul li button div.jsoneditor-expand {
- position: absolute;
- top: 0;
- right: 0;
- width: 24px;
- height: 24px;
- padding: 0;
- margin: 0 4px 0 0;
- background: url("img/jsoneditor-icons.svg") 0 -72px;
-}
-
-div.jsoneditor-contextmenu div.jsoneditor-separator {
+.jsoneditor-contextmenu .jsoneditor-separator {
height: 0;
border-top: 1px solid #e5e5e5;
padding-top: 5px;
margin-top: 5px;
}
-div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-remove .jsoneditor-icon {
background-position: -24px 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-append .jsoneditor-icon {
background-position: 0 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-insert .jsoneditor-icon {
background-position: 0 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-duplicate .jsoneditor-icon {
background-position: -48px 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-sort-asc .jsoneditor-icon {
background-position: -168px 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-sort-desc .jsoneditor-icon {
background-position: -192px 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-transform > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-transform .jsoneditor-icon {
background-position: -216px 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-extract > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-extract .jsoneditor-icon {
background-position: 0 -24px;
}
-/* ContextMenu - sub menu */
-
-div.jsoneditor-contextmenu ul li button.jsoneditor-selected,
-div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover,
-div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus {
- color: white;
- background-color: #ee422e;
-}
-
-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 ul li button {
- padding-left: 24px;
- animation: all ease-in-out 1s;
-}
-
-div.jsoneditor-contextmenu ul li ul li button:hover,
-div.jsoneditor-contextmenu ul li ul li button:focus {
- background-color: #f5f5f5;
-}
-
-div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-type-string .jsoneditor-icon {
background-position: -144px 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-type-auto .jsoneditor-icon {
background-position: -120px 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-type-object .jsoneditor-icon {
background-position: -72px 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-type-array .jsoneditor-icon {
background-position: -96px 0;
}
-div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
+.jsoneditor-contextmenu button.jsoneditor-type-modes .jsoneditor-icon {
background-image: none;
width: 6px;
}
-/* pico modal styling */
+.jsoneditor-contextmenu ul,
+.jsoneditor-contextmenu li {
+ box-sizing: content-box;
+ position: relative;
+}
-.jsoneditor-modal-overlay {
- position: absolute !important;
- background: rgb(1,1,1) !important;
- opacity: 0.3 !important;
+.jsoneditor-contextmenu .jsoneditor-menu button:hover,
+.jsoneditor-contextmenu .jsoneditor-menu button:focus {
+ color: #1a1a1a;
+ background-color: #f5f5f5;
+ outline: none;
+}
+
+.jsoneditor-contextmenu .jsoneditor-menu li button.jsoneditor-selected,
+.jsoneditor-contextmenu .jsoneditor-menu li button.jsoneditor-selected:hover,
+.jsoneditor-contextmenu .jsoneditor-menu li button.jsoneditor-selected:focus {
+ color: #ffffff;
+ background-color: #ee422e;
+}
+
+.jsoneditor-contextmenu .jsoneditor-menu li ul li button:hover,
+.jsoneditor-contextmenu .jsoneditor-menu li ul li button:focus {
+ background-color: #f5f5f5;
}
.jsoneditor-modal {
- position: absolute !important;
- max-width: 95% !important;
- width: auto !important;
+ max-width: 95%;
border-radius: 2px !important;
padding: 45px 15px 15px 15px !important;
- box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3) !important;
+ box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
color: #4d4d4d;
line-height: 1.3em;
}
@@ -953,41 +839,17 @@ div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
font-family: arial, sans-serif;
font-size: 11pt;
background: #3883fa;
- color: white;
+ color: #ffffff;
}
.jsoneditor-modal table {
width: 100%;
}
-.jsoneditor-modal table th,
-.jsoneditor-modal table td {
- text-align: left;
- vertical-align: top;
- font-weight: normal;
- color: #4d4d4d;
- border-spacing: 0;
- border-collapse: collapse;
-}
-
.jsoneditor-modal table td {
padding: 3px 0;
}
-.jsoneditor-modal p:first-child {
- margin-top: 0;
-}
-
-.jsoneditor-modal a {
- color: #3883fa;
-}
-
-
-
-.jsoneditor-modal .jsoneditor-jmespath-block {
- margin-bottom: 10px;
-}
-
.jsoneditor-modal table td.jsoneditor-modal-input {
text-align: right;
padding-right: 0;
@@ -998,56 +860,28 @@ div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
padding-top: 15px;
}
+.jsoneditor-modal table th {
+ vertical-align: middle;
+}
+
+.jsoneditor-modal p:first-child {
+ margin-top: 0;
+}
+
+.jsoneditor-modal a {
+ color: #3883fa;
+}
+
+.jsoneditor-modal .jsoneditor-jmespath-block {
+ margin-bottom: 10px;
+}
+
.jsoneditor-modal .pico-close {
background: none !important;
font-size: 24px !important;
top: 7px !important;
right: 7px !important;
- color: white;
-}
-
-.jsoneditor-modal select,
-.jsoneditor-modal textarea,
-.jsoneditor-modal input,
-.jsoneditor-modal #query {
- background: #ffffff;
- border: 1px solid #d3d3d3;
- color: #4d4d4d;
- border-radius: 3px;
- padding: 4px;
-}
-
-.jsoneditor-modal,
-.jsoneditor-modal table td,
-.jsoneditor-modal table th,
-.jsoneditor-modal select,
-.jsoneditor-modal option,
-.jsoneditor-modal textarea,
-.jsoneditor-modal input,
-.jsoneditor-modal #query {
- font-size: 10.5pt;
- font-family: arial, sans-serif;
-}
-
-.jsoneditor-modal table th {
- vertical-align: middle;
-}
-
-.jsoneditor-modal #query,
-.jsoneditor-modal .jsoneditor-transform-preview {
- font-family: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif;
- font-size: 10pt;
-}
-
-.jsoneditor-modal input[type="button"],
-.jsoneditor-modal input[type="submit"] {
- background: #f5f5f5;
- padding: 4px 20px;
-}
-
-.jsoneditor-modal select,
-.jsoneditor-modal input {
- cursor: pointer;
+ color: #ffffff;
}
.jsoneditor-modal input {
@@ -1116,19 +950,6 @@ div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
border-bottom-right-radius: 3px;
}
-.jsoneditor-modal .jsoneditor-button-group.jsoneditor-button-group-value-asc input.jsoneditor-button-asc,
-.jsoneditor-modal .jsoneditor-button-group.jsoneditor-button-group-value-desc input.jsoneditor-button-desc {
- background: #3883fa;
- border-color: #3883fa;
- color: white;
-}
-
-.jsoneditor-modal #query,
-.jsoneditor-modal .jsoneditor-transform-preview {
- width: 100%;
- box-sizing: border-box;
-}
-
.jsoneditor-modal .jsoneditor-transform-preview {
background: #f5f5f5;
height: 200px;
@@ -1212,7 +1033,66 @@ div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
background-color: #3883fa;
border-radius: 5px;
}
-div.jsoneditor-menu {
+
+.jsoneditor-modal table th,
+.jsoneditor-modal table td {
+ text-align: left;
+ vertical-align: top;
+ font-weight: normal;
+ color: #4d4d4d;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+
+.jsoneditor-modal select,
+.jsoneditor-modal textarea,
+.jsoneditor-modal input,
+.jsoneditor-modal #query {
+ background: #ffffff;
+ border: 1px solid #d3d3d3;
+ color: #4d4d4d;
+ border-radius: 3px;
+ padding: 4px;
+}
+
+.jsoneditor-modal,
+.jsoneditor-modal table td,
+.jsoneditor-modal table th,
+.jsoneditor-modal select,
+.jsoneditor-modal option,
+.jsoneditor-modal textarea,
+.jsoneditor-modal input,
+.jsoneditor-modal #query {
+ font-size: 10.5pt;
+ font-family: arial, sans-serif;
+}
+
+.jsoneditor-modal #query,
+.jsoneditor-modal .jsoneditor-transform-preview {
+ font-family: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif;
+ font-size: 10pt;
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.jsoneditor-modal input[type="button"],
+.jsoneditor-modal input[type="submit"] {
+ background: #f5f5f5;
+ padding: 4px 20px;
+}
+
+.jsoneditor-modal select,
+.jsoneditor-modal input {
+ cursor: pointer;
+}
+
+.jsoneditor-modal .jsoneditor-button-group.jsoneditor-button-group-value-asc input.jsoneditor-button-asc,
+.jsoneditor-modal .jsoneditor-button-group.jsoneditor-button-group-value-desc input.jsoneditor-button-desc {
+ background: #3883fa;
+ border-color: #3883fa;
+ color: #ffffff;
+}
+.jsoneditor-menu {
width: 100%;
height: 35px;
padding: 2px;
@@ -1220,13 +1100,13 @@ div.jsoneditor-menu {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
- color: white;
+ color: #ffffff;
background-color: #3883fa;
border-bottom: 1px solid #3883fa;
}
-div.jsoneditor-menu > button,
-div.jsoneditor-menu > div.jsoneditor-modes > button {
+.jsoneditor-menu > button,
+.jsoneditor-menu > .jsoneditor-modes > button {
width: 26px;
height: 26px;
margin: 2px;
@@ -1234,137 +1114,121 @@ div.jsoneditor-menu > div.jsoneditor-modes > button {
border-radius: 2px;
border: 1px solid transparent;
background: transparent url("img/jsoneditor-icons.svg");
- color: white;
+ color: #ffffff;
opacity: 0.8;
font-family: arial, sans-serif;
font-size: 10pt;
float: left;
}
-div.jsoneditor-menu > button:hover,
-div.jsoneditor-menu > div.jsoneditor-modes > button:hover {
- background-color: rgba(255,255,255,0.2);
- border: 1px solid rgba(255,255,255,0.4);
+.jsoneditor-menu > button:hover,
+.jsoneditor-menu > .jsoneditor-modes > button:hover {
+ background-color: rgba(255, 255, 255, 0.2);
+ border: 1px solid rgba(255, 255, 255, 0.4);
}
-div.jsoneditor-menu > button:focus,
-div.jsoneditor-menu > button:active,
-div.jsoneditor-menu > div.jsoneditor-modes > button:focus,
-div.jsoneditor-menu > div.jsoneditor-modes > button:active {
- background-color: rgba(255,255,255,0.3);
+.jsoneditor-menu > button:focus,
+.jsoneditor-menu > button:active,
+.jsoneditor-menu > .jsoneditor-modes > button:focus,
+.jsoneditor-menu > .jsoneditor-modes > button:active {
+ background-color: rgba(255, 255, 255, 0.3);
}
-div.jsoneditor-menu > button:disabled,
-div.jsoneditor-menu > div.jsoneditor-modes > button:disabled {
+.jsoneditor-menu > button:disabled,
+.jsoneditor-menu > .jsoneditor-modes > button:disabled {
opacity: 0.5;
background-color: transparent;
border: none;
}
-div.jsoneditor-menu > button.jsoneditor-collapse-all {
+.jsoneditor-menu > button.jsoneditor-collapse-all {
background-position: 0 -96px;
}
-div.jsoneditor-menu > button.jsoneditor-expand-all {
+.jsoneditor-menu > button.jsoneditor-expand-all {
background-position: 0 -120px;
}
-div.jsoneditor-menu > button.jsoneditor-sort {
+.jsoneditor-menu > button.jsoneditor-sort {
background-position: -120px -96px;
}
-div.jsoneditor-menu > button.jsoneditor-transform {
+.jsoneditor-menu > button.jsoneditor-transform {
background-position: -144px -96px;
}
-div.jsoneditor.jsoneditor-mode-view > div.jsoneditor-menu > button.jsoneditor-sort,
-div.jsoneditor.jsoneditor-mode-form > div.jsoneditor-menu > button.jsoneditor-sort,
-div.jsoneditor.jsoneditor-mode-view > div.jsoneditor-menu > button.jsoneditor-transform,
-div.jsoneditor.jsoneditor-mode-form > div.jsoneditor-menu > button.jsoneditor-transform {
+.jsoneditor.jsoneditor-mode-view > .jsoneditor-menu > button.jsoneditor-sort,
+.jsoneditor.jsoneditor-mode-form > .jsoneditor-menu > button.jsoneditor-sort,
+.jsoneditor.jsoneditor-mode-view > .jsoneditor-menu > button.jsoneditor-transform,
+.jsoneditor.jsoneditor-mode-form > .jsoneditor-menu > button.jsoneditor-transform {
display: none;
}
-div.jsoneditor-menu > button.jsoneditor-undo {
+.jsoneditor-menu > button.jsoneditor-undo {
background-position: -24px -96px;
}
-div.jsoneditor-menu > button.jsoneditor-undo:disabled {
+.jsoneditor-menu > button.jsoneditor-undo:disabled {
background-position: -24px -120px;
}
-div.jsoneditor-menu > button.jsoneditor-redo {
+.jsoneditor-menu > button.jsoneditor-redo {
background-position: -48px -96px;
}
-div.jsoneditor-menu > button.jsoneditor-redo:disabled {
+.jsoneditor-menu > button.jsoneditor-redo:disabled {
background-position: -48px -120px;
}
-div.jsoneditor-menu > button.jsoneditor-compact {
+.jsoneditor-menu > button.jsoneditor-compact {
background-position: -72px -96px;
}
-div.jsoneditor-menu > button.jsoneditor-format {
+.jsoneditor-menu > button.jsoneditor-format {
background-position: -72px -120px;
}
-div.jsoneditor-menu > button.jsoneditor-repair {
+.jsoneditor-menu > button.jsoneditor-repair {
background-position: -96px -96px;
}
-div.jsoneditor-menu > div.jsoneditor-modes {
+.jsoneditor-menu > .jsoneditor-modes {
display: inline-block;
float: left;
}
-div.jsoneditor-menu > div.jsoneditor-modes > button {
+.jsoneditor-menu > .jsoneditor-modes > button {
background-image: none;
width: auto;
padding-left: 6px;
padding-right: 6px;
}
-div.jsoneditor-menu > button.jsoneditor-separator,
-div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator {
+.jsoneditor-menu > button.jsoneditor-separator,
+.jsoneditor-menu > .jsoneditor-modes > button.jsoneditor-separator {
margin-left: 10px;
}
-div.jsoneditor-menu a {
+.jsoneditor-menu a {
font-family: arial, sans-serif;
font-size: 10pt;
- color: white;
+ color: #ffffff;
opacity: 0.8;
vertical-align: middle;
}
-div.jsoneditor-menu a:hover {
+.jsoneditor-menu a:hover {
opacity: 1;
}
-div.jsoneditor-menu a.jsoneditor-poweredBy {
+.jsoneditor-menu a.jsoneditor-poweredBy {
font-size: 8pt;
position: absolute;
right: 0;
top: 0;
padding: 10px;
}
-table.jsoneditor-search input,
-table.jsoneditor-search div.jsoneditor-results {
- font-family: arial, sans-serif;
- font-size: 10pt;
- color: #1A1A1A;
- background: transparent;
- /* For Firefox */
-}
-
-table.jsoneditor-search div.jsoneditor-results {
- color: white;
- padding-right: 5px;
- line-height: 24px;
- padding-top: 2px;
-}
-
-table.jsoneditor-search {
+.jsoneditor-search {
position: absolute;
right: 4px;
top: 4px;
@@ -1372,18 +1236,20 @@ table.jsoneditor-search {
border-spacing: 0;
}
-table.jsoneditor-search div.jsoneditor-frame {
+.jsoneditor-search .jsoneditor-results {
+ color: #ffffff;
+ padding-right: 5px;
+ line-height: 26px;
+}
+
+.jsoneditor-search .jsoneditor-frame {
border: 1px solid transparent;
- background-color: white;
+ background-color: #ffffff;
padding: 0 2px;
margin: 0;
}
-table.jsoneditor-search div.jsoneditor-frame table {
- border-collapse: collapse;
-}
-
-table.jsoneditor-search input {
+.jsoneditor-search input {
width: 120px;
border: none;
outline: none;
@@ -1391,7 +1257,7 @@ table.jsoneditor-search input {
line-height: 20px;
}
-table.jsoneditor-search button {
+.jsoneditor-search button {
width: 16px;
height: 24px;
padding: 0;
@@ -1401,36 +1267,41 @@ table.jsoneditor-search button {
vertical-align: top;
}
-table.jsoneditor-search button:hover {
+.jsoneditor-search button:hover {
background-color: transparent;
}
-table.jsoneditor-search button.jsoneditor-refresh {
+.jsoneditor-search button.jsoneditor-refresh {
width: 18px;
background-position: -99px -73px;
}
-table.jsoneditor-search button.jsoneditor-next {
+.jsoneditor-search button.jsoneditor-next {
cursor: pointer;
background-position: -124px -73px;
}
-table.jsoneditor-search button.jsoneditor-next:hover {
+.jsoneditor-search button.jsoneditor-next:hover {
background-position: -124px -49px;
}
-table.jsoneditor-search button.jsoneditor-previous {
+.jsoneditor-search button.jsoneditor-previous {
cursor: pointer;
background-position: -148px -73px;
margin-right: 2px;
}
-table.jsoneditor-search button.jsoneditor-previous:hover {
+.jsoneditor-search button.jsoneditor-previous:hover {
background-position: -148px -49px;
}
-div.jsoneditor div.autocomplete.dropdown {
+
+.jsoneditor-search input,
+.jsoneditor-search .jsoneditor-results {
+ font-family: arial, sans-serif;
+}
+.jsoneditor.autocomplete.dropdown {
position: absolute;
- background: white;
+ background: #ffffff;
box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
border: 1px solid #d3d3d3;
z-index: 100;
@@ -1446,27 +1317,27 @@ div.jsoneditor div.autocomplete.dropdown {
font-size: 10pt;
}
-div.jsoneditor div.autocomplete.dropdown .item {
+.jsoneditor.autocomplete.dropdown .item {
color: #333;
}
-div.jsoneditor div.autocomplete.dropdown .item.hover {
+.jsoneditor.autocomplete.dropdown .item.hover {
background-color: #ddd;
}
-div.jsoneditor div.autocomplete.hint {
+.jsoneditor.autocomplete.hint {
color: #aaa;
top: 4px;
left: 4px;
}
-div.jsoneditor-treepath {
+.jsoneditor-treepath {
padding: 0 5px;
overflow: hidden;
white-space: nowrap;
outline: none;
}
-div.jsoneditor-treepath.show-all {
+.jsoneditor-treepath.show-all {
word-wrap: break-word;
white-space: normal;
position: absolute;
@@ -1475,12 +1346,16 @@ div.jsoneditor-treepath.show-all {
box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
}
-div.jsoneditor-treepath div.jsoneditor-contextmenu-root {
+.jsoneditor-treepath.show-all span.jsoneditor-treepath-show-all-btn {
+ display: none;
+}
+
+.jsoneditor-treepath div.jsoneditor-contextmenu-root {
position: absolute;
left: 0;
}
-div.jsoneditor-treepath span.jsoneditor-treepath-show-all-btn {
+.jsoneditor-treepath .jsoneditor-treepath-show-all-btn {
position: absolute;
background-color: #ebebeb;
left: 0;
@@ -1489,28 +1364,24 @@ div.jsoneditor-treepath span.jsoneditor-treepath-show-all-btn {
cursor: pointer;
}
-div.jsoneditor-treepath.show-all span.jsoneditor-treepath-show-all-btn {
- display: none;
-}
-
-div.jsoneditor-treepath span.jsoneditor-treepath-element {
+.jsoneditor-treepath .jsoneditor-treepath-element {
margin: 1px;
font-family: arial, sans-serif;
font-size: 10pt;
}
-div.jsoneditor-treepath span.jsoneditor-treepath-seperator {
+.jsoneditor-treepath .jsoneditor-treepath-seperator {
margin: 2px;
font-size: 9pt;
font-family: arial, sans-serif;
}
-div.jsoneditor-treepath span.jsoneditor-treepath-element:hover,
-div.jsoneditor-treepath span.jsoneditor-treepath-seperator:hover {
+.jsoneditor-treepath span.jsoneditor-treepath-element:hover,
+.jsoneditor-treepath span.jsoneditor-treepath-seperator:hover {
cursor: pointer;
text-decoration: underline;
}
-div.jsoneditor-statusbar {
+.jsoneditor-statusbar {
line-height: 26px;
height: 26px;
color: #808080;
@@ -1522,20 +1393,15 @@ div.jsoneditor-statusbar {
font-size: 10pt;
}
-div.jsoneditor-statusbar > .jsoneditor-curserinfo-label,
-div.jsoneditor-statusbar > .jsoneditor-size-info {
- margin: 0 4px;
-}
-
-div.jsoneditor-statusbar > .jsoneditor-curserinfo-val {
+.jsoneditor-statusbar .jsoneditor-curserinfo-val {
margin-right: 12px;
}
-div.jsoneditor-statusbar > .jsoneditor-curserinfo-count {
+.jsoneditor-statusbar .jsoneditor-curserinfo-count {
margin-left: 4px;
}
-div.jsoneditor-statusbar > .jsoneditor-validation-error-icon {
+.jsoneditor-statusbar .jsoneditor-validation-error-icon {
float: right;
width: 24px;
height: 24px;
@@ -1545,13 +1411,13 @@ div.jsoneditor-statusbar > .jsoneditor-validation-error-icon {
cursor: pointer;
}
-div.jsoneditor-statusbar > .jsoneditor-validation-error-count {
+.jsoneditor-statusbar .jsoneditor-validation-error-count {
float: right;
margin: 0 4px 0 0;
cursor: pointer;
}
-div.jsoneditor-statusbar > .jsoneditor-parse-error-icon {
+.jsoneditor-statusbar .jsoneditor-parse-error-icon {
float: right;
width: 24px;
height: 24px;
@@ -1560,10 +1426,15 @@ div.jsoneditor-statusbar > .jsoneditor-parse-error-icon {
background: url("img/jsoneditor-icons.svg") -25px 0px;
}
-div.jsoneditor-statusbar .jsoneditor-array-info a {
+.jsoneditor-statusbar .jsoneditor-array-info a {
color: inherit;
}
-div.jsoneditor-navigation-bar {
+
+.jsoneditor-statusbar .jsoneditor-curserinfo-label,
+.jsoneditor-statusbar .jsoneditor-size-info {
+ margin: 0 4px;
+}
+.jsoneditor-navigation-bar {
width: 100%;
height: 26px;
line-height: 26px;
@@ -1638,9 +1509,9 @@ div.jsoneditor-navigation-bar {
width: 100%;
padding: 7px 28px 7px 14px;
cursor: pointer;
- border: 1px solid #999;
+ border: 1px solid #999999;
border-radius: 3px;
- background-color: #fff;
+ background-color: #ffffff;
}
.selectr-selected::before {
@@ -1696,7 +1567,7 @@ div.jsoneditor-navigation-bar {
padding: 2px 25px 2px 8px;
margin: 0 2px 2px 0;
cursor: default;
- color: #fff;
+ color: #ffffff;
border: medium none;
border-radius: 10px;
background: #acb7bf none repeat scroll 0 0;
@@ -1716,9 +1587,9 @@ div.jsoneditor-navigation-bar {
width: 100%;
border-width: 0 1px 1px;
border-style: solid;
- border-color: transparent #999 #999;
+ border-color: transparent #999999 #999999;
border-radius: 0 0 3px 3px;
- background-color: #fff;
+ background-color: #ffffff;
}
.selectr-container.open .selectr-options-container {
@@ -1784,7 +1655,7 @@ div.jsoneditor-navigation-bar {
top: 4px;
width: 3px;
height: 12px;
- background-color: #fff;
+ background-color: #ffffff;
}
.selectr-clear:before,
@@ -1819,7 +1690,7 @@ div.jsoneditor-navigation-bar {
width: calc(100% - 30px);
margin: 10px 15px;
padding: 7px 30px 7px 9px;
- border: 1px solid #999;
+ border: 1px solid #999999;
border-radius: 3px;
}
@@ -1828,9 +1699,9 @@ div.jsoneditor-navigation-bar {
box-sizing: border-box;
width: 100%;
padding: 8px 16px;
- border-top: 1px solid #999;
+ border-top: 1px solid #999999;
border-radius: 0 0 3px 3px;
- background-color: #fff;
+ background-color: #ffffff;
}
.selectr-container.notice .selectr-notice {
@@ -1891,7 +1762,7 @@ div.jsoneditor-navigation-bar {
}
.selectr-option.active {
- color: #fff;
+ color: #ffffff;
background-color: #5897fb;
}
@@ -1904,7 +1775,7 @@ div.jsoneditor-navigation-bar {
}
.selectr-container.open .selectr-selected {
- border-color: #999 #999 transparent #999;
+ border-color: #999999 #999999 transparent #999999;
border-radius: 3px 3px 0 0;
}
@@ -2020,15 +1891,15 @@ div.jsoneditor-navigation-bar {
}
.selectr-container.open.inverted .selectr-selected {
- border-color: transparent #999 #999;
+ border-color: transparent #999999 #999999;
border-radius: 0 0 3px 3px;
}
.selectr-container.inverted .selectr-options-container {
border-width: 1px 1px 0;
- border-color: #999 #999 transparent;
+ border-color: #999999 #999999 transparent;
border-radius: 3px 3px 0 0;
- background-color: #fff;
+ background-color: #ffffff;
}
.selectr-container.inverted .selectr-options-container {
diff --git a/dist/jsoneditor.js b/dist/jsoneditor.js
index 1f4c9b7..5602cfd 100644
--- a/dist/jsoneditor.js
+++ b/dist/jsoneditor.js
@@ -128,1442 +128,1442 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-
-
-__webpack_require__(23);
-var naturalSort = __webpack_require__(24);
-var jsonlint = __webpack_require__(72);
-var jsonMap = __webpack_require__(73);
-var translate = __webpack_require__(1).translate;
-
-var MAX_ITEMS_FIELDS_COLLECTION = 10000;
-
-/**
- * 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
- * @return {JSON} json
- */
-exports.parse = function parse(jsonString) {
- try {
- return JSON.parse(jsonString);
- }
- catch (err) {
- // try to throw a more detailed error message using validate
- exports.validate(jsonString);
-
- // rethrow the original error
- throw err;
- }
-};
-
-/**
- * Repair a JSON-like string containing. For example changes JavaScript
- * notation into JSON notation.
- * This function for example changes a string like "{a: 2, 'b': {c: 'd'}"
- * into '{"a": 2, "b": {"c": "d"}'
- * @param {string} jsString
- * @returns {string} json
- */
-exports.repair = function (jsString) {
- // TODO: refactor this function, it's too large and complicated now
-
- // escape all single and double quotes inside strings
- var chars = [];
- var i = 0;
-
- //If JSON starts with a function (characters/digits/"_-"), remove this function.
- //This is useful for "stripping" JSONP objects to become JSON
- //For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}]
- var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/);
- if (match) {
- jsString = match[3];
- }
-
- var controlChars = {
- '\b': '\\b',
- '\f': '\\f',
- '\n': '\\n',
- '\r': '\\r',
- '\t': '\\t'
- };
-
- var quote = '\'';
- var quoteDbl = '"';
- var quoteLeft = '\u2018';
- var quoteRight = '\u2019';
- var quoteDblLeft = '\u201C';
- var quoteDblRight = '\u201D';
- var graveAccent = '\u0060';
- var acuteAccent = '\u00B4';
-
- // helper functions to get the current/prev/next character
- function curr () { return jsString.charAt(i); }
- function next() { return jsString.charAt(i + 1); }
- function prev() { return jsString.charAt(i - 1); }
-
- function isWhiteSpace(c) {
- return c === ' ' || c === '\n' || c === '\r' || c === '\t';
- }
-
- // get the last parsed non-whitespace character
- function lastNonWhitespace () {
- var p = chars.length - 1;
-
- while (p >= 0) {
- var pp = chars[p];
- if (!isWhiteSpace(pp)) {
- return pp;
- }
- p--;
- }
-
- return '';
- }
-
- // get at the first next non-white space character
- function nextNonWhiteSpace() {
- var iNext = i + 1;
- while (iNext < jsString.length && isWhiteSpace(jsString[iNext])) {
- iNext++;
- }
-
- return jsString[iNext];
- }
-
- // skip a block comment '/* ... */'
- function skipBlockComment () {
- i += 2;
- while (i < jsString.length && (curr() !== '*' || next() !== '/')) {
- i++;
- }
- i += 2;
- }
-
- // skip a comment '// ...'
- function skipComment () {
- i += 2;
- while (i < jsString.length && (curr() !== '\n')) {
- i++;
- }
- }
-
- /**
- * parse single or double quoted string. Returns the parsed string
- * @param {string} endQuote
- * @return {string}
- */
- function parseString(endQuote) {
- var string = '';
-
- string += '"';
- i++;
- var c = curr();
- while (i < jsString.length && c !== endQuote) {
- if (c === '"' && prev() !== '\\') {
- // unescaped double quote, escape it
- string += '\\"';
- }
- else if (controlChars.hasOwnProperty(c)) {
- // replace unescaped control characters with escaped ones
- string += controlChars[c]
- }
- else if (c === '\\') {
- // remove the escape character when followed by a single quote ', not needed
- i++;
- c = curr();
- if (c !== '\'') {
- string += '\\';
- }
- string += c;
- }
- else {
- // regular character
- string += c;
- }
-
- i++;
- c = curr();
- }
- if (c === endQuote) {
- string += '"';
- i++;
- }
-
- return string;
- }
-
- // parse an unquoted key
- function parseKey() {
- var specialValues = ['null', 'true', 'false'];
- var key = '';
- var c = curr();
-
- var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character
- while (regexp.test(c)) {
- key += c;
- i++;
- c = curr();
- }
-
- if (specialValues.indexOf(key) === -1) {
- return '"' + key + '"';
- }
- else {
- return key;
- }
- }
-
- function parseMongoDataType () {
- var c = curr();
- var value;
- var dataType = '';
- while (/[a-zA-Z_$]/.test(c)) {
- dataType += c
- i++;
- c = curr();
- }
-
- if (dataType.length > 0 && c === '(') {
- // This is an MongoDB data type like {"_id": ObjectId("123")}
- i++;
- c = curr();
- if (c === '"') {
- // a data type containing a string, like ISODate("2012-12-19T06:01:17.171Z")
- value = parseString(c);
- c = curr();
- }
- else {
- // a data type containing a value, like 'NumberLong(2)'
- value = '';
- while(c !== ')' && c !== '') {
- value += c;
- i++;
- c = curr();
- }
- }
-
- if (c === ')') {
- // skip the closing bracket at the end
- i++;
-
- // return the value (strip the data type object)
- return value;
- }
- else {
- // huh? that's unexpected. don't touch it
- return dataType + '(' + value + c;
- }
- }
- else {
- // hm, no Mongo data type after all
- return dataType;
- }
- }
-
- function isSpecialWhiteSpace (c) {
- return (
- c === '\u00A0' ||
- (c >= '\u2000' && c <= '\u200A') ||
- c === '\u202F' ||
- c === '\u205F' ||
- c === '\u3000')
- }
-
- while(i < jsString.length) {
- var c = curr();
-
- if (c === '/' && next() === '*') {
- skipBlockComment();
- }
- else if (c === '/' && next() === '/') {
- skipComment();
- }
- else if (isSpecialWhiteSpace(c)) {
- // special white spaces (like non breaking space)
- chars.push(' ');
- i++
- }
- else if (c === quote) {
- chars.push(parseString(c));
- }
- else if (c === quoteDbl) {
- chars.push(parseString(quoteDbl));
- }
- else if (c === graveAccent) {
- chars.push(parseString(acuteAccent));
- }
- else if (c === quoteLeft) {
- chars.push(parseString(quoteRight));
- }
- else if (c === quoteDblLeft) {
- chars.push(parseString(quoteDblRight));
- }
- else if (c === ',' && [']', '}'].indexOf(nextNonWhiteSpace()) !== -1) {
- // skip trailing commas
- i++;
- }
- else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) {
- // an unquoted object key (like a in '{a:2}')
- chars.push(parseKey());
- }
- else {
- if (/[a-zA-Z_$]/.test(c)) {
- chars.push(parseMongoDataType());
- }
- else {
- chars.push(c);
- i++;
- }
- }
- }
-
- return chars.join('');
-};
-
-/**
- * Escape unicode characters.
- * For example input '\u2661' (length 1) will output '\\u2661' (length 5).
- * @param {string} text
- * @return {string}
- */
-exports.escapeUnicodeChars = function (text) {
- // see https://www.wikiwand.com/en/UTF-16
- // note: we leave surrogate pairs as two individual chars,
- // as JSON doesn't interpret them as a single unicode char.
- return text.replace(/[\u007F-\uFFFF]/g, function(c) {
- return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4);
- })
-};
-
-/**
- * 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
- * @throws Error
- */
-exports.validate = function validate(jsonString) {
- if (typeof(jsonlint) != 'undefined') {
- jsonlint.parse(jsonString);
- }
- else {
- JSON.parse(jsonString);
- }
-};
-
-/**
- * Extend object a with the properties of object b
- * @param {Object} a
- * @param {Object} b
- * @return {Object} a
- */
-exports.extend = function extend(a, b) {
- for (var prop in b) {
- if (b.hasOwnProperty(prop)) {
- a[prop] = b[prop];
- }
- }
- return a;
-};
-
-/**
- * Remove all properties from object a
- * @param {Object} a
- * @return {Object} a
- */
-exports.clear = function clear (a) {
- for (var prop in a) {
- if (a.hasOwnProperty(prop)) {
- delete a[prop];
- }
- }
- return a;
-};
-
-/**
- * Get the type of an object
- * @param {*} object
- * @return {String} type
- */
-exports.type = function type (object) {
- if (object === null) {
- return 'null';
- }
- if (object === undefined) {
- return 'undefined';
- }
- if ((object instanceof Number) || (typeof object === 'number')) {
- return 'number';
- }
- if ((object instanceof String) || (typeof object === 'string')) {
- return 'string';
- }
- if ((object instanceof Boolean) || (typeof object === 'boolean')) {
- return 'boolean';
- }
- if ((object instanceof RegExp) || (typeof object === 'regexp')) {
- return 'regexp';
- }
- if (exports.isArray(object)) {
- return 'array';
- }
-
- return 'object';
-};
-
-/**
- * Test whether a text contains a url (matches when a string starts
- * with 'http://*' or 'https://*' and has no whitespace characters)
- * @param {String} text
- */
-var isUrlRegex = /^https?:\/\/\S+$/;
-exports.isUrl = function isUrl (text) {
- return (typeof text == 'string' || text instanceof String) &&
- isUrlRegex.test(text);
-};
-
-/**
- * Tes whether given object is an Array
- * @param {*} obj
- * @returns {boolean} returns true when obj is an array
- */
-exports.isArray = function (obj) {
- return Object.prototype.toString.call(obj) === '[object Array]';
-};
-
-/**
- * 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.
- */
-exports.getAbsoluteLeft = function getAbsoluteLeft(elem) {
- var rect = elem.getBoundingClientRect();
- return rect.left + window.pageXOffset || document.scrollLeft || 0;
-};
-
-/**
- * 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.
- */
-exports.getAbsoluteTop = function getAbsoluteTop(elem) {
- var rect = elem.getBoundingClientRect();
- return rect.top + window.pageYOffset || document.scrollTop || 0;
-};
-
-/**
- * add a className to the given elements style
- * @param {Element} elem
- * @param {String} className
- */
-exports.addClassName = function addClassName(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(' ');
- }
-};
-
-/**
- * remove all classes from the given elements style
- * @param {Element} elem
- */
-exports.removeAllClassNames = function removeAllClassNames(elem) {
- elem.className = "";
-};
-
-/**
- * add a className to the given elements style
- * @param {Element} elem
- * @param {String} className
- */
-exports.removeClassName = function removeClassName(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
- */
-exports.stripFormatting = function stripFormatting(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
- exports.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 A content editable div
- */
-exports.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) {
- var range, selection;
- if(document.createRange) {
- 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
- }
-};
-
-/**
- * Select all text of a content editable div.
- * http://stackoverflow.com/a/3806004/1262753
- * @param {Element} contentEditableElement A content editable div
- */
-exports.selectContentEditable = function selectContentEditable(contentEditableElement) {
- if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') {
- return;
- }
-
- var sel, range;
- if (window.getSelection && document.createRange) {
- range = document.createRange();
- range.selectNodeContents(contentEditableElement);
- sel = window.getSelection();
- sel.removeAllRanges();
- sel.addRange(range);
- }
-};
-
-/**
- * Get text selection
- * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
- * @return {Range | TextRange | null} range
- */
-exports.getSelection = function getSelection() {
- if (window.getSelection) {
- var sel = window.getSelection();
- if (sel.getRangeAt && sel.rangeCount) {
- return sel.getRangeAt(0);
- }
- }
- return null;
-};
-
-/**
- * Set text selection
- * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
- * @param {Range | TextRange | null} range
- */
-exports.setSelection = function setSelection(range) {
- if (range) {
- if (window.getSelection) {
- var sel = window.getSelection();
- sel.removeAllRanges();
- sel.addRange(range);
- }
- }
-};
-
-/**
- * Get selected text range
- * @return {Object} params object containing parameters:
- * {Number} startOffset
- * {Number} endOffset
- * {Element} container HTML element holding the
- * selected text element
- * Returns null if no text selection is found
- */
-exports.getSelectionOffset = function getSelectionOffset() {
- var range = exports.getSelection();
-
- if (range && 'startOffset' in range && 'endOffset' in range &&
- range.startContainer && (range.startContainer == range.endContainer)) {
- return {
- startOffset: range.startOffset,
- endOffset: range.endOffset,
- container: range.startContainer.parentNode
- };
- }
-
- return null;
-};
-
-/**
- * Set selected text range in given element
- * @param {Object} params An object containing:
- * {Element} container
- * {Number} startOffset
- * {Number} endOffset
- */
-exports.setSelectionOffset = function setSelectionOffset(params) {
- if (document.createRange && window.getSelection) {
- var selection = window.getSelection();
- if(selection) {
- var range = document.createRange();
-
- if (!params.container.firstChild) {
- params.container.appendChild(document.createTextNode(''));
- }
-
- // TODO: do not suppose that the first child of the container is a textnode,
- // but recursively find the textnodes
- range.setStart(params.container.firstChild, params.startOffset);
- range.setEnd(params.container.firstChild, params.endOffset);
-
- exports.setSelection(range);
- }
- }
-};
-
-/**
- * Get the inner text of an HTML element (for example a div element)
- * @param {Element} element
- * @param {Object} [buffer]
- * @return {String} innerText
- */
-exports.getInnerText = function getInnerText(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 += exports.getInnerText(child, buffer);
- buffer.set('\n');
- }
- else if (child.nodeName == 'BR') {
- innerText += buffer.flush();
- buffer.set('\n');
- }
- else {
- innerText += exports.getInnerText(child, buffer);
- }
- }
-
- return innerText;
- }
- else {
- if (element.nodeName == 'P' && exports.getInternetExplorerVersion() != -1) {
- // On Internet Explorer, a
with hasChildNodes()==false is
- // rendered with a new line. Note that a
with
- // hasChildNodes()==true is rendered without a new line
- // Other browsers always ensure there is a
inside the
,
- // and if not, the
does not render a new line
- return buffer.flush();
- }
- }
-
- // br or unknown
- return '';
-};
-
-/**
- * Test whether an element has the provided parent node somewhere up the node tree.
- * @param {Element} elem
- * @param {Element} parent
- * @return {boolean}
- */
-exports.hasParentNode = function (elem, parent) {
- var e = elem ? elem.parentNode : undefined;
-
- while (e) {
- if (e === parent) {
- return true;
- }
- e = e.parentNode;
- }
-
- return false;
-}
-
-/**
- * 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
- */
-exports.getInternetExplorerVersion = function getInternetExplorerVersion() {
- if (_ieVersion == -1) {
- var rv = -1; // Return value assumes failure.
- if (typeof navigator !== 'undefined' && 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 );
- }
- }
-
- _ieVersion = rv;
- }
-
- return _ieVersion;
-};
-
-/**
- * Test whether the current browser is Firefox
- * @returns {boolean} isFirefox
- */
-exports.isFirefox = function isFirefox () {
- return (typeof navigator !== 'undefined' && navigator.userAgent.indexOf("Firefox") !== -1);
-};
-
-/**
- * cached internet explorer version
- * @type {Number}
- * @private
- */
-var _ieVersion = -1;
-
-/**
- * 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
- */
-exports.addEventListener = function addEventListener(element, action, listener, useCapture) {
- if (element.addEventListener) {
- if (useCapture === undefined)
- useCapture = false;
-
- if (action === "mousewheel" && exports.isFirefox()) {
- action = "DOMMouseScroll"; // For Firefox
- }
-
- element.addEventListener(action, listener, useCapture);
- return listener;
- } else if (element.attachEvent) {
- // Old 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
- */
-exports.removeEventListener = function removeEventListener(element, action, listener, useCapture) {
- if (element.removeEventListener) {
- if (useCapture === undefined)
- useCapture = false;
-
- if (action === "mousewheel" && exports.isFirefox()) {
- action = "DOMMouseScroll"; // For Firefox
- }
-
- element.removeEventListener(action, listener, useCapture);
- } else if (element.detachEvent) {
- // Old IE browsers
- element.detachEvent("on" + action, listener);
- }
-};
-
-/**
- * Test if an element is a child of a parent element.
- * @param {Element} elem
- * @param {Element} parent
- * @return {boolean} returns true if elem is a child of the parent
- */
-exports.isChildOf = function (elem, parent) {
- var e = elem.parentNode;
- while (e) {
- if (e === parent) {
- return true;
- }
- e = e.parentNode;
- }
-
- return false;
-};
-
-/**
- * Parse a JSON path like '.items[3].name' into an array
- * @param {string} jsonPath
- * @return {Array}
- */
-exports.parsePath = function parsePath(jsonPath) {
- var path = [];
- var i = 0;
-
- function parseProperty () {
- var prop = ''
- while (jsonPath[i] !== undefined && /[\w$]/.test(jsonPath[i])) {
- prop += jsonPath[i];
- i++;
- }
-
- if (prop === '') {
- throw new Error('Invalid JSON path: property name expected at index ' + i);
- }
-
- return prop;
- }
-
- function parseIndex (end) {
- var name = ''
- while (jsonPath[i] !== undefined && jsonPath[i] !== end) {
- name += jsonPath[i];
- i++;
- }
-
- if (jsonPath[i] !== end) {
- throw new Error('Invalid JSON path: unexpected end, character ' + end + ' expected')
- }
-
- return name;
- }
-
- while (jsonPath[i] !== undefined) {
- if (jsonPath[i] === '.') {
- i++;
- path.push(parseProperty());
- }
- else if (jsonPath[i] === '[') {
- i++;
-
- if (jsonPath[i] === '\'' || jsonPath[i] === '"') {
- var end = jsonPath[i]
- i++;
-
- path.push(parseIndex(end));
-
- if (jsonPath[i] !== end) {
- throw new Error('Invalid JSON path: closing quote \' expected at index ' + i)
- }
- i++;
- }
- else {
- var index = parseIndex(']').trim()
- if (index.length === 0) {
- throw new Error('Invalid JSON path: array value expected at index ' + i)
- }
- // Coerce numeric indices to numbers, but ignore star
- index = index === '*' ? index : JSON.parse(index);
- path.push(index);
- }
-
- if (jsonPath[i] !== ']') {
- throw new Error('Invalid JSON path: closing bracket ] expected at index ' + i)
- }
- i++;
- }
- else {
- throw new Error('Invalid JSON path: unexpected character "' + jsonPath[i] + '" at index ' + i);
- }
- }
-
- return path;
-};
-
-/**
- * Stringify an array with a path in a JSON path like '.items[3].name'
- * @param {Array.} path
- * @returns {string}
- */
-exports.stringifyPath = function stringifyPath(path) {
- return path
- .map(function (p) {
- if (typeof p === 'number'){
- return ('[' + p + ']');
- } else if(typeof p === 'string' && p.match(/^[A-Za-z0-9_$]+$/)) {
- return '.' + p;
- } else {
- return '["' + p + '"]';
- }
- })
- .join('');
-};
-
-/**
- * Improve the error message of a JSON schema error
- * @param {Object} error
- * @return {Object} The error
- */
-exports.improveSchemaError = function (error) {
- if (error.keyword === 'enum' && Array.isArray(error.schema)) {
- var enums = error.schema;
- if (enums) {
- enums = enums.map(function (value) {
- return JSON.stringify(value);
- });
-
- if (enums.length > 5) {
- var more = ['(' + (enums.length - 5) + ' more...)'];
- enums = enums.slice(0, 5);
- enums.push(more);
- }
- error.message = 'should be equal to one of: ' + enums.join(', ');
- }
- }
-
- if (error.keyword === 'additionalProperties') {
- error.message = 'should NOT have additional property: ' + error.params.additionalProperty;
- }
-
- return error;
-};
-
-/**
- * Test whether something is a Promise
- * @param {*} object
- * @returns {boolean} Returns true when object is a promise, false otherwise
- */
-exports.isPromise = function (object) {
- return object && typeof object.then === 'function' && typeof object.catch === 'function';
-};
-
-/**
- * Test whether a custom validation error has the correct structure
- * @param {*} validationError The error to be checked.
- * @returns {boolean} Returns true if the structure is ok, false otherwise
- */
-exports.isValidValidationError = function (validationError) {
- return typeof validationError === 'object' &&
- Array.isArray(validationError.path) &&
- typeof validationError.message === 'string';
-};
-
-/**
- * Test whether the child rect fits completely inside the parent rect.
- * @param {ClientRect} parent
- * @param {ClientRect} child
- * @param {number} margin
- */
-exports.insideRect = function (parent, child, margin) {
- var _margin = margin !== undefined ? margin : 0;
- return child.left - _margin >= parent.left
- && child.right + _margin <= parent.right
- && child.top - _margin >= parent.top
- && child.bottom + _margin <= parent.bottom;
-};
-
-/**
- * Returns a function, that, as long as it continues to be invoked, will not
- * be triggered. The function will be called after it stops being called for
- * N milliseconds.
- *
- * Source: https://davidwalsh.name/javascript-debounce-function
- *
- * @param {function} func
- * @param {number} wait Number in milliseconds
- * @param {boolean} [immediate=false] If `immediate` is passed, trigger the
- * function on the leading edge, instead
- * of the trailing.
- * @return {function} Return the debounced function
- */
-exports.debounce = function debounce(func, wait, immediate) {
- var timeout;
- return function() {
- var context = this, args = arguments;
- var later = function() {
- timeout = null;
- if (!immediate) func.apply(context, args);
- };
- var callNow = immediate && !timeout;
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- if (callNow) func.apply(context, args);
- };
-};
-
-/**
- * Determines the difference between two texts.
- * Can only detect one removed or inserted block of characters.
- * @param {string} oldText
- * @param {string} newText
- * @return {{start: number, end: number}} Returns the start and end
- * of the changed part in newText.
- */
-exports.textDiff = function textDiff(oldText, newText) {
- var len = newText.length;
- var start = 0;
- var oldEnd = oldText.length;
- var newEnd = newText.length;
-
- while (newText.charAt(start) === oldText.charAt(start)
- && start < len) {
- start++;
- }
-
- while (newText.charAt(newEnd - 1) === oldText.charAt(oldEnd - 1)
- && newEnd > start && oldEnd > 0) {
- newEnd--;
- oldEnd--;
- }
-
- return {start: start, end: newEnd};
-};
-
-
-/**
- * Return an object with the selection range or cursor position (if both have the same value)
- * Support also old browsers (IE8-)
- * Source: http://ourcodeworld.com/articles/read/282/how-to-get-the-current-cursor-position-and-selection-within-a-text-input-or-textarea-in-javascript
- * @param {DOMElement} el A dom element of a textarea or input text.
- * @return {Object} reference Object with 2 properties (start and end) with the identifier of the location of the cursor and selected text.
- **/
-exports.getInputSelection = function(el) {
- var startIndex = 0, endIndex = 0, normalizedValue, range, textInputRange, len, endRange;
-
- if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
- startIndex = el.selectionStart;
- endIndex = el.selectionEnd;
- } else {
- range = document.selection.createRange();
-
- if (range && range.parentElement() == el) {
- len = el.value.length;
- normalizedValue = el.value.replace(/\r\n/g, "\n");
-
- // Create a working TextRange that lives only in the input
- textInputRange = el.createTextRange();
- textInputRange.moveToBookmark(range.getBookmark());
-
- // Check if the startIndex and endIndex of the selection are at the very end
- // of the input, since moveStart/moveEnd doesn't return what we want
- // in those cases
- endRange = el.createTextRange();
- endRange.collapse(false);
-
- if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
- startIndex = endIndex = len;
- } else {
- startIndex = -textInputRange.moveStart("character", -len);
- startIndex += normalizedValue.slice(0, startIndex).split("\n").length - 1;
-
- if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
- endIndex = len;
- } else {
- endIndex = -textInputRange.moveEnd("character", -len);
- endIndex += normalizedValue.slice(0, endIndex).split("\n").length - 1;
- }
- }
- }
- }
-
- return {
- startIndex: startIndex,
- endIndex: endIndex,
- start: _positionForIndex(startIndex),
- end: _positionForIndex(endIndex)
- };
-
- /**
- * Returns textarea row and column position for certain index
- * @param {Number} index text index
- * @returns {{row: Number, col: Number}}
- */
- function _positionForIndex(index) {
- var textTillIndex = el.value.substring(0,index);
- var row = (textTillIndex.match(/\n/g) || []).length + 1;
- var col = textTillIndex.length - textTillIndex.lastIndexOf("\n");
-
- return {
- row: row,
- column: col
- }
- }
-}
-
-/**
- * Returns the index for certaion position in text element
- * @param {DOMElement} el A dom element of a textarea or input text.
- * @param {Number} row row value, > 0, if exceeds rows number - last row will be returned
- * @param {Number} column column value, > 0, if exceeds column length - end of column will be returned
- * @returns {Number} index of position in text, -1 if not found
- */
-exports.getIndexForPosition = function(el, row, column) {
- var text = el.value || '';
- if (row > 0 && column > 0) {
- var rows = text.split('\n', row);
- row = Math.min(rows.length, row);
- column = Math.min(rows[row - 1].length, column - 1);
- var columnCount = (row == 1 ? column : column + 1); // count new line on multiple rows
- return rows.slice(0, row - 1).join('\n').length + columnCount;
- }
- return -1;
-}
-
-/**
- * Returns location of json paths in certain json string
- * @param {String} text json string
- * @param {Array} paths array of json paths
- * @returns {Array<{path: String, line: Number, row: Number}>}
- */
-exports.getPositionForPath = function(text, paths) {
- var me = this;
- var result = [];
- var jsmap;
- if (!paths || !paths.length) {
- return result;
- }
-
- try {
- jsmap = jsonMap.parse(text);
- } catch (err) {
- return result;
- }
-
- paths.forEach(function (path) {
- var pathArr = me.parsePath(path);
- var pointerName = pathArr.length ? "/" + pathArr.join("/") : "";
- var pointer = jsmap.pointers[pointerName];
- if (pointer) {
- result.push({
- path: path,
- line: pointer.key ? pointer.key.line : (pointer.value ? pointer.value.line : 0),
- column: pointer.key ? pointer.key.column : (pointer.value ? pointer.value.column : 0)
- });
- }
- });
-
- return result;
-
-}
-
-/**
- * Get the applied color given a color name or code
- * Source: https://stackoverflow.com/questions/6386090/validating-css-color-names/33184805
- * @param {string} color
- * @returns {string | null} returns the color if the input is a valid
- * color, and returns null otherwise. Example output:
- * 'rgba(255,0,0,0.7)' or 'rgb(255,0,0)'
- */
-exports.getColorCSS = function (color) {
- var ele = document.createElement('div');
- ele.style.color = color;
- return ele.style.color.split(/\s+/).join('').toLowerCase() || null;
-}
-
-/**
- * Test if a string contains a valid color name or code.
- * @param {string} color
- * @returns {boolean} returns true if a valid color, false otherwise
- */
-exports.isValidColor = function (color) {
- return !!exports.getColorCSS(color);
-}
-
-/**
- * Make a tooltip for a field based on the field's schema.
- * @param {object} schema JSON schema
- * @param {string} [locale] Locale code (for example, zh-CN)
- * @returns {string} Field tooltip, may be empty string if all relevant schema properties are missing
- */
-exports.makeFieldTooltip = function (schema, locale) {
- if (!schema) {
- return '';
- }
-
- var tooltip = '';
- if (schema.title) {
- tooltip += schema.title;
- }
-
- if (schema.description) {
- if (tooltip.length > 0) {
- tooltip += '\n';
- }
- tooltip += schema.description;
- }
-
- if (schema.default) {
- if (tooltip.length > 0) {
- tooltip += '\n\n';
- }
- tooltip += translate('default', undefined, locale) + '\n';
- tooltip += JSON.stringify(schema.default, null, 2);
- }
-
- if (Array.isArray(schema.examples) && schema.examples.length > 0) {
- if (tooltip.length > 0) {
- tooltip += '\n\n';
- }
- tooltip += translate('examples', undefined, locale) + '\n';
- schema.examples.forEach(function (example, index) {
- tooltip += JSON.stringify(example, null, 2);
- if (index !== schema.examples.length - 1) {
- tooltip += '\n';
- }
- });
- }
-
- return tooltip;
-}
-
-/**
- * Get a nested property from an object.
- * Returns undefined when the property does not exist.
- * @param {Object} object
- * @param {string[]} path
- * @return {*}
- */
-exports.get = function (object, path) {
- var value = object
-
- for (var i = 0; i < path.length && value !== undefined && value !== null; i++) {
- value = value[path[i]]
- }
-
- return value;
-}
-
-/**
- * Find a unique name. Suffix the name with ' (copy)', '(copy 2)', etc
- * until a unique name is found
- * @param {string} name
- * @param {Array} existingPropNames Array with existing prop names
- */
-exports.findUniqueName = function(name, existingPropNames) {
- var strippedName = name.replace(/ \(copy( \d+)?\)$/, '')
- var validName = strippedName
- var i = 1
-
- while (existingPropNames.indexOf(validName) !== -1) {
- var copy = 'copy' + (i > 1 ? (' ' + i) : '')
- validName = strippedName + ' (' + copy + ')'
- i++
- }
-
- return validName
-}
-
-/**
- * Get the child paths of an array
- * @param {JSON} json
- * @param {boolean} [includeObjects=false] If true, object and array paths are returned as well
- * @return {string[]}
- */
-exports.getChildPaths = function (json, includeObjects) {
- var pathsMap = {};
-
- function getObjectChildPaths (json, pathsMap, rootPath, includeObjects) {
- var isValue = !Array.isArray(json) && !exports.isObject(json)
-
- if (isValue || includeObjects) {
- pathsMap[rootPath || ''] = true;
- }
-
- if (exports.isObject(json)) {
- Object.keys(json).forEach(function (field) {
- getObjectChildPaths(json[field], pathsMap, rootPath + '.' + field, includeObjects);
- });
- }
- }
-
- if (Array.isArray(json)) {
- var max = Math.min(json.length, MAX_ITEMS_FIELDS_COLLECTION);
- for (var i = 0; i < max; i++) {
- var item = json[i];
- getObjectChildPaths(item, pathsMap, '', includeObjects);
- }
- }
- else {
- pathsMap[''] = true;
- }
-
- return Object.keys(pathsMap).sort();
-}
-
-/**
- * Sort object keys using natural sort
- * @param {Array} array
- * @param {String} [path] JSON pointer
- * @param {'asc' | 'desc'} [direction]
- */
-exports.sort = function (array, path, direction) {
- var parsedPath = path && path !== '.' ? exports.parsePath(path) : []
- var sign = direction === 'desc' ? -1: 1
-
- var sortedArray = array.slice()
- sortedArray.sort(function (a, b) {
- var aValue = exports.get(a, parsedPath);
- var bValue = exports.get(b, parsedPath);
-
- return sign * (aValue > bValue ? 1 : aValue < bValue ? -1 : 0);
- })
-
- return sortedArray;
-}
-
-/**
- * Sort object keys using natural sort
- * @param {Object} object
- * @param {'asc' | 'desc'} [direction]
- */
-exports.sortObjectKeys = function (object, direction) {
- var sign = (direction === 'desc') ? -1 : 1;
- var sortedFields = Object.keys(object).sort(function (a, b) {
- return sign * naturalSort(a, b);
- });
-
- var sortedObject = {};
- sortedFields.forEach(function (field) {
- sortedObject[field] = object[field];
- });
-
- return sortedObject;
-}
-
-/**
- * Cast contents of a string to the correct type.
- * This can be a string, a number, a boolean, etc
- * @param {String} str
- * @return {*} castedStr
- * @private
- */
-exports.parseString = function(str) {
- var lower = str.toLowerCase();
- var num = Number(str); // will nicely fail with '123ab'
- var numFloat = parseFloat(str); // will nicely fail with ' '
-
- if (str === '') {
- return '';
- }
- else if (lower === 'null') {
- return null;
- }
- else if (lower === 'true') {
- return true;
- }
- else if (lower === 'false') {
- return false;
- }
- else if (!isNaN(num) && !isNaN(numFloat)) {
- return num;
- }
- else {
- return str;
- }
-};
-
-/**
- * Return a human readable document size
- * For example formatSize(7570718) outputs '7.2 MiB'
- * @param {number} size
- * @return {string} Returns a human readable size
- */
-exports.formatSize = function (size) {
- if (size < 900) {
- return size.toFixed() + ' B';
- }
-
- var KiB = size / 1024;
- if (KiB < 900) {
- return KiB.toFixed(1) + ' KiB';
- }
-
- var MiB = KiB / 1024;
- if (MiB < 900) {
- return MiB.toFixed(1) + ' MiB';
- }
-
- var GiB = MiB / 1024;
- if (GiB < 900) {
- return GiB.toFixed(1) + ' GiB';
- }
-
- var TiB = GiB / 1024;
- return TiB.toFixed(1) + ' TiB';
-}
-
-/**
- * Limit text to a maximum number of characters
- * @param {string} text
- * @param {number} maxCharacterCount
- * @return {string} Returns the limited text,
- * ending with '...' if the max was exceeded
- */
-exports.limitCharacters = function (text, maxCharacterCount) {
- if (text.length <= maxCharacterCount) {
- return text;
- }
-
- return text.slice(0, maxCharacterCount) + '...';
-}
-
-/**
- * Test whether a value is an Object
- * @param {*} value
- * @return {boolean}
- */
-exports.isObject = function (value) {
- return typeof value === 'object' && value !== null && !Array.isArray(value)
-}
-
-/**
- * Helper function to test whether an array contains an item
- * @param {Array} array
- * @param {*} item
- * @return {boolean} Returns true if `item` is in `array`, returns false otherwise.
- */
-exports.contains = function (array, item) {
- return array.indexOf(item) !== -1;
-}
+
+
+__webpack_require__(23);
+var naturalSort = __webpack_require__(24);
+var jsonlint = __webpack_require__(72);
+var jsonMap = __webpack_require__(73);
+var translate = __webpack_require__(1).translate;
+
+var MAX_ITEMS_FIELDS_COLLECTION = 10000;
+
+/**
+ * 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
+ * @return {JSON} json
+ */
+exports.parse = function parse(jsonString) {
+ try {
+ return JSON.parse(jsonString);
+ }
+ catch (err) {
+ // try to throw a more detailed error message using validate
+ exports.validate(jsonString);
+
+ // rethrow the original error
+ throw err;
+ }
+};
+
+/**
+ * Repair a JSON-like string containing. For example changes JavaScript
+ * notation into JSON notation.
+ * This function for example changes a string like "{a: 2, 'b': {c: 'd'}"
+ * into '{"a": 2, "b": {"c": "d"}'
+ * @param {string} jsString
+ * @returns {string} json
+ */
+exports.repair = function (jsString) {
+ // TODO: refactor this function, it's too large and complicated now
+
+ // escape all single and double quotes inside strings
+ var chars = [];
+ var i = 0;
+
+ //If JSON starts with a function (characters/digits/"_-"), remove this function.
+ //This is useful for "stripping" JSONP objects to become JSON
+ //For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}]
+ var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/);
+ if (match) {
+ jsString = match[3];
+ }
+
+ var controlChars = {
+ '\b': '\\b',
+ '\f': '\\f',
+ '\n': '\\n',
+ '\r': '\\r',
+ '\t': '\\t'
+ };
+
+ var quote = '\'';
+ var quoteDbl = '"';
+ var quoteLeft = '\u2018';
+ var quoteRight = '\u2019';
+ var quoteDblLeft = '\u201C';
+ var quoteDblRight = '\u201D';
+ var graveAccent = '\u0060';
+ var acuteAccent = '\u00B4';
+
+ // helper functions to get the current/prev/next character
+ function curr () { return jsString.charAt(i); }
+ function next() { return jsString.charAt(i + 1); }
+ function prev() { return jsString.charAt(i - 1); }
+
+ function isWhiteSpace(c) {
+ return c === ' ' || c === '\n' || c === '\r' || c === '\t';
+ }
+
+ // get the last parsed non-whitespace character
+ function lastNonWhitespace () {
+ var p = chars.length - 1;
+
+ while (p >= 0) {
+ var pp = chars[p];
+ if (!isWhiteSpace(pp)) {
+ return pp;
+ }
+ p--;
+ }
+
+ return '';
+ }
+
+ // get at the first next non-white space character
+ function nextNonWhiteSpace() {
+ var iNext = i + 1;
+ while (iNext < jsString.length && isWhiteSpace(jsString[iNext])) {
+ iNext++;
+ }
+
+ return jsString[iNext];
+ }
+
+ // skip a block comment '/* ... */'
+ function skipBlockComment () {
+ i += 2;
+ while (i < jsString.length && (curr() !== '*' || next() !== '/')) {
+ i++;
+ }
+ i += 2;
+ }
+
+ // skip a comment '// ...'
+ function skipComment () {
+ i += 2;
+ while (i < jsString.length && (curr() !== '\n')) {
+ i++;
+ }
+ }
+
+ /**
+ * parse single or double quoted string. Returns the parsed string
+ * @param {string} endQuote
+ * @return {string}
+ */
+ function parseString(endQuote) {
+ var string = '';
+
+ string += '"';
+ i++;
+ var c = curr();
+ while (i < jsString.length && c !== endQuote) {
+ if (c === '"' && prev() !== '\\') {
+ // unescaped double quote, escape it
+ string += '\\"';
+ }
+ else if (controlChars.hasOwnProperty(c)) {
+ // replace unescaped control characters with escaped ones
+ string += controlChars[c]
+ }
+ else if (c === '\\') {
+ // remove the escape character when followed by a single quote ', not needed
+ i++;
+ c = curr();
+ if (c !== '\'') {
+ string += '\\';
+ }
+ string += c;
+ }
+ else {
+ // regular character
+ string += c;
+ }
+
+ i++;
+ c = curr();
+ }
+ if (c === endQuote) {
+ string += '"';
+ i++;
+ }
+
+ return string;
+ }
+
+ // parse an unquoted key
+ function parseKey() {
+ var specialValues = ['null', 'true', 'false'];
+ var key = '';
+ var c = curr();
+
+ var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character
+ while (regexp.test(c)) {
+ key += c;
+ i++;
+ c = curr();
+ }
+
+ if (specialValues.indexOf(key) === -1) {
+ return '"' + key + '"';
+ }
+ else {
+ return key;
+ }
+ }
+
+ function parseMongoDataType () {
+ var c = curr();
+ var value;
+ var dataType = '';
+ while (/[a-zA-Z_$]/.test(c)) {
+ dataType += c
+ i++;
+ c = curr();
+ }
+
+ if (dataType.length > 0 && c === '(') {
+ // This is an MongoDB data type like {"_id": ObjectId("123")}
+ i++;
+ c = curr();
+ if (c === '"') {
+ // a data type containing a string, like ISODate("2012-12-19T06:01:17.171Z")
+ value = parseString(c);
+ c = curr();
+ }
+ else {
+ // a data type containing a value, like 'NumberLong(2)'
+ value = '';
+ while(c !== ')' && c !== '') {
+ value += c;
+ i++;
+ c = curr();
+ }
+ }
+
+ if (c === ')') {
+ // skip the closing bracket at the end
+ i++;
+
+ // return the value (strip the data type object)
+ return value;
+ }
+ else {
+ // huh? that's unexpected. don't touch it
+ return dataType + '(' + value + c;
+ }
+ }
+ else {
+ // hm, no Mongo data type after all
+ return dataType;
+ }
+ }
+
+ function isSpecialWhiteSpace (c) {
+ return (
+ c === '\u00A0' ||
+ (c >= '\u2000' && c <= '\u200A') ||
+ c === '\u202F' ||
+ c === '\u205F' ||
+ c === '\u3000')
+ }
+
+ while(i < jsString.length) {
+ var c = curr();
+
+ if (c === '/' && next() === '*') {
+ skipBlockComment();
+ }
+ else if (c === '/' && next() === '/') {
+ skipComment();
+ }
+ else if (isSpecialWhiteSpace(c)) {
+ // special white spaces (like non breaking space)
+ chars.push(' ');
+ i++
+ }
+ else if (c === quote) {
+ chars.push(parseString(c));
+ }
+ else if (c === quoteDbl) {
+ chars.push(parseString(quoteDbl));
+ }
+ else if (c === graveAccent) {
+ chars.push(parseString(acuteAccent));
+ }
+ else if (c === quoteLeft) {
+ chars.push(parseString(quoteRight));
+ }
+ else if (c === quoteDblLeft) {
+ chars.push(parseString(quoteDblRight));
+ }
+ else if (c === ',' && [']', '}'].indexOf(nextNonWhiteSpace()) !== -1) {
+ // skip trailing commas
+ i++;
+ }
+ else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) {
+ // an unquoted object key (like a in '{a:2}')
+ chars.push(parseKey());
+ }
+ else {
+ if (/[a-zA-Z_$]/.test(c)) {
+ chars.push(parseMongoDataType());
+ }
+ else {
+ chars.push(c);
+ i++;
+ }
+ }
+ }
+
+ return chars.join('');
+};
+
+/**
+ * Escape unicode characters.
+ * For example input '\u2661' (length 1) will output '\\u2661' (length 5).
+ * @param {string} text
+ * @return {string}
+ */
+exports.escapeUnicodeChars = function (text) {
+ // see https://www.wikiwand.com/en/UTF-16
+ // note: we leave surrogate pairs as two individual chars,
+ // as JSON doesn't interpret them as a single unicode char.
+ return text.replace(/[\u007F-\uFFFF]/g, function(c) {
+ return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4);
+ })
+};
+
+/**
+ * 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
+ * @throws Error
+ */
+exports.validate = function validate(jsonString) {
+ if (typeof(jsonlint) != 'undefined') {
+ jsonlint.parse(jsonString);
+ }
+ else {
+ JSON.parse(jsonString);
+ }
+};
+
+/**
+ * Extend object a with the properties of object b
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Object} a
+ */
+exports.extend = function extend(a, b) {
+ for (var prop in b) {
+ if (b.hasOwnProperty(prop)) {
+ a[prop] = b[prop];
+ }
+ }
+ return a;
+};
+
+/**
+ * Remove all properties from object a
+ * @param {Object} a
+ * @return {Object} a
+ */
+exports.clear = function clear (a) {
+ for (var prop in a) {
+ if (a.hasOwnProperty(prop)) {
+ delete a[prop];
+ }
+ }
+ return a;
+};
+
+/**
+ * Get the type of an object
+ * @param {*} object
+ * @return {String} type
+ */
+exports.type = function type (object) {
+ if (object === null) {
+ return 'null';
+ }
+ if (object === undefined) {
+ return 'undefined';
+ }
+ if ((object instanceof Number) || (typeof object === 'number')) {
+ return 'number';
+ }
+ if ((object instanceof String) || (typeof object === 'string')) {
+ return 'string';
+ }
+ if ((object instanceof Boolean) || (typeof object === 'boolean')) {
+ return 'boolean';
+ }
+ if ((object instanceof RegExp) || (typeof object === 'regexp')) {
+ return 'regexp';
+ }
+ if (exports.isArray(object)) {
+ return 'array';
+ }
+
+ return 'object';
+};
+
+/**
+ * Test whether a text contains a url (matches when a string starts
+ * with 'http://*' or 'https://*' and has no whitespace characters)
+ * @param {String} text
+ */
+var isUrlRegex = /^https?:\/\/\S+$/;
+exports.isUrl = function isUrl (text) {
+ return (typeof text == 'string' || text instanceof String) &&
+ isUrlRegex.test(text);
+};
+
+/**
+ * Tes whether given object is an Array
+ * @param {*} obj
+ * @returns {boolean} returns true when obj is an array
+ */
+exports.isArray = function (obj) {
+ return Object.prototype.toString.call(obj) === '[object Array]';
+};
+
+/**
+ * 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.
+ */
+exports.getAbsoluteLeft = function getAbsoluteLeft(elem) {
+ var rect = elem.getBoundingClientRect();
+ return rect.left + window.pageXOffset || document.scrollLeft || 0;
+};
+
+/**
+ * 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.
+ */
+exports.getAbsoluteTop = function getAbsoluteTop(elem) {
+ var rect = elem.getBoundingClientRect();
+ return rect.top + window.pageYOffset || document.scrollTop || 0;
+};
+
+/**
+ * add a className to the given elements style
+ * @param {Element} elem
+ * @param {String} className
+ */
+exports.addClassName = function addClassName(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(' ');
+ }
+};
+
+/**
+ * remove all classes from the given elements style
+ * @param {Element} elem
+ */
+exports.removeAllClassNames = function removeAllClassNames(elem) {
+ elem.className = "";
+};
+
+/**
+ * add a className to the given elements style
+ * @param {Element} elem
+ * @param {String} className
+ */
+exports.removeClassName = function removeClassName(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
+ */
+exports.stripFormatting = function stripFormatting(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
+ exports.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 A content editable div
+ */
+exports.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) {
+ var range, selection;
+ if(document.createRange) {
+ 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
+ }
+};
+
+/**
+ * Select all text of a content editable div.
+ * http://stackoverflow.com/a/3806004/1262753
+ * @param {Element} contentEditableElement A content editable div
+ */
+exports.selectContentEditable = function selectContentEditable(contentEditableElement) {
+ if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') {
+ return;
+ }
+
+ var sel, range;
+ if (window.getSelection && document.createRange) {
+ range = document.createRange();
+ range.selectNodeContents(contentEditableElement);
+ sel = window.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+};
+
+/**
+ * Get text selection
+ * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
+ * @return {Range | TextRange | null} range
+ */
+exports.getSelection = function getSelection() {
+ if (window.getSelection) {
+ var sel = window.getSelection();
+ if (sel.getRangeAt && sel.rangeCount) {
+ return sel.getRangeAt(0);
+ }
+ }
+ return null;
+};
+
+/**
+ * Set text selection
+ * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
+ * @param {Range | TextRange | null} range
+ */
+exports.setSelection = function setSelection(range) {
+ if (range) {
+ if (window.getSelection) {
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ }
+};
+
+/**
+ * Get selected text range
+ * @return {Object} params object containing parameters:
+ * {Number} startOffset
+ * {Number} endOffset
+ * {Element} container HTML element holding the
+ * selected text element
+ * Returns null if no text selection is found
+ */
+exports.getSelectionOffset = function getSelectionOffset() {
+ var range = exports.getSelection();
+
+ if (range && 'startOffset' in range && 'endOffset' in range &&
+ range.startContainer && (range.startContainer == range.endContainer)) {
+ return {
+ startOffset: range.startOffset,
+ endOffset: range.endOffset,
+ container: range.startContainer.parentNode
+ };
+ }
+
+ return null;
+};
+
+/**
+ * Set selected text range in given element
+ * @param {Object} params An object containing:
+ * {Element} container
+ * {Number} startOffset
+ * {Number} endOffset
+ */
+exports.setSelectionOffset = function setSelectionOffset(params) {
+ if (document.createRange && window.getSelection) {
+ var selection = window.getSelection();
+ if(selection) {
+ var range = document.createRange();
+
+ if (!params.container.firstChild) {
+ params.container.appendChild(document.createTextNode(''));
+ }
+
+ // TODO: do not suppose that the first child of the container is a textnode,
+ // but recursively find the textnodes
+ range.setStart(params.container.firstChild, params.startOffset);
+ range.setEnd(params.container.firstChild, params.endOffset);
+
+ exports.setSelection(range);
+ }
+ }
+};
+
+/**
+ * Get the inner text of an HTML element (for example a div element)
+ * @param {Element} element
+ * @param {Object} [buffer]
+ * @return {String} innerText
+ */
+exports.getInnerText = function getInnerText(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 += exports.getInnerText(child, buffer);
+ buffer.set('\n');
+ }
+ else if (child.nodeName == 'BR') {
+ innerText += buffer.flush();
+ buffer.set('\n');
+ }
+ else {
+ innerText += exports.getInnerText(child, buffer);
+ }
+ }
+
+ return innerText;
+ }
+ else {
+ if (element.nodeName == 'P' && exports.getInternetExplorerVersion() != -1) {
+ // On Internet Explorer, a with hasChildNodes()==false is
+ // rendered with a new line. Note that a
with
+ // hasChildNodes()==true is rendered without a new line
+ // Other browsers always ensure there is a
inside the
,
+ // and if not, the
does not render a new line
+ return buffer.flush();
+ }
+ }
+
+ // br or unknown
+ return '';
+};
+
+/**
+ * Test whether an element has the provided parent node somewhere up the node tree.
+ * @param {Element} elem
+ * @param {Element} parent
+ * @return {boolean}
+ */
+exports.hasParentNode = function (elem, parent) {
+ var e = elem ? elem.parentNode : undefined;
+
+ while (e) {
+ if (e === parent) {
+ return true;
+ }
+ e = e.parentNode;
+ }
+
+ return false;
+}
+
+/**
+ * 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
+ */
+exports.getInternetExplorerVersion = function getInternetExplorerVersion() {
+ if (_ieVersion == -1) {
+ var rv = -1; // Return value assumes failure.
+ if (typeof navigator !== 'undefined' && 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 );
+ }
+ }
+
+ _ieVersion = rv;
+ }
+
+ return _ieVersion;
+};
+
+/**
+ * Test whether the current browser is Firefox
+ * @returns {boolean} isFirefox
+ */
+exports.isFirefox = function isFirefox () {
+ return (typeof navigator !== 'undefined' && navigator.userAgent.indexOf("Firefox") !== -1);
+};
+
+/**
+ * cached internet explorer version
+ * @type {Number}
+ * @private
+ */
+var _ieVersion = -1;
+
+/**
+ * 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
+ */
+exports.addEventListener = function addEventListener(element, action, listener, useCapture) {
+ if (element.addEventListener) {
+ if (useCapture === undefined)
+ useCapture = false;
+
+ if (action === "mousewheel" && exports.isFirefox()) {
+ action = "DOMMouseScroll"; // For Firefox
+ }
+
+ element.addEventListener(action, listener, useCapture);
+ return listener;
+ } else if (element.attachEvent) {
+ // Old 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
+ */
+exports.removeEventListener = function removeEventListener(element, action, listener, useCapture) {
+ if (element.removeEventListener) {
+ if (useCapture === undefined)
+ useCapture = false;
+
+ if (action === "mousewheel" && exports.isFirefox()) {
+ action = "DOMMouseScroll"; // For Firefox
+ }
+
+ element.removeEventListener(action, listener, useCapture);
+ } else if (element.detachEvent) {
+ // Old IE browsers
+ element.detachEvent("on" + action, listener);
+ }
+};
+
+/**
+ * Test if an element is a child of a parent element.
+ * @param {Element} elem
+ * @param {Element} parent
+ * @return {boolean} returns true if elem is a child of the parent
+ */
+exports.isChildOf = function (elem, parent) {
+ var e = elem.parentNode;
+ while (e) {
+ if (e === parent) {
+ return true;
+ }
+ e = e.parentNode;
+ }
+
+ return false;
+};
+
+/**
+ * Parse a JSON path like '.items[3].name' into an array
+ * @param {string} jsonPath
+ * @return {Array}
+ */
+exports.parsePath = function parsePath(jsonPath) {
+ var path = [];
+ var i = 0;
+
+ function parseProperty () {
+ var prop = ''
+ while (jsonPath[i] !== undefined && /[\w$]/.test(jsonPath[i])) {
+ prop += jsonPath[i];
+ i++;
+ }
+
+ if (prop === '') {
+ throw new Error('Invalid JSON path: property name expected at index ' + i);
+ }
+
+ return prop;
+ }
+
+ function parseIndex (end) {
+ var name = ''
+ while (jsonPath[i] !== undefined && jsonPath[i] !== end) {
+ name += jsonPath[i];
+ i++;
+ }
+
+ if (jsonPath[i] !== end) {
+ throw new Error('Invalid JSON path: unexpected end, character ' + end + ' expected')
+ }
+
+ return name;
+ }
+
+ while (jsonPath[i] !== undefined) {
+ if (jsonPath[i] === '.') {
+ i++;
+ path.push(parseProperty());
+ }
+ else if (jsonPath[i] === '[') {
+ i++;
+
+ if (jsonPath[i] === '\'' || jsonPath[i] === '"') {
+ var end = jsonPath[i]
+ i++;
+
+ path.push(parseIndex(end));
+
+ if (jsonPath[i] !== end) {
+ throw new Error('Invalid JSON path: closing quote \' expected at index ' + i)
+ }
+ i++;
+ }
+ else {
+ var index = parseIndex(']').trim()
+ if (index.length === 0) {
+ throw new Error('Invalid JSON path: array value expected at index ' + i)
+ }
+ // Coerce numeric indices to numbers, but ignore star
+ index = index === '*' ? index : JSON.parse(index);
+ path.push(index);
+ }
+
+ if (jsonPath[i] !== ']') {
+ throw new Error('Invalid JSON path: closing bracket ] expected at index ' + i)
+ }
+ i++;
+ }
+ else {
+ throw new Error('Invalid JSON path: unexpected character "' + jsonPath[i] + '" at index ' + i);
+ }
+ }
+
+ return path;
+};
+
+/**
+ * Stringify an array with a path in a JSON path like '.items[3].name'
+ * @param {Array.} path
+ * @returns {string}
+ */
+exports.stringifyPath = function stringifyPath(path) {
+ return path
+ .map(function (p) {
+ if (typeof p === 'number'){
+ return ('[' + p + ']');
+ } else if(typeof p === 'string' && p.match(/^[A-Za-z0-9_$]+$/)) {
+ return '.' + p;
+ } else {
+ return '["' + p + '"]';
+ }
+ })
+ .join('');
+};
+
+/**
+ * Improve the error message of a JSON schema error
+ * @param {Object} error
+ * @return {Object} The error
+ */
+exports.improveSchemaError = function (error) {
+ if (error.keyword === 'enum' && Array.isArray(error.schema)) {
+ var enums = error.schema;
+ if (enums) {
+ enums = enums.map(function (value) {
+ return JSON.stringify(value);
+ });
+
+ if (enums.length > 5) {
+ var more = ['(' + (enums.length - 5) + ' more...)'];
+ enums = enums.slice(0, 5);
+ enums.push(more);
+ }
+ error.message = 'should be equal to one of: ' + enums.join(', ');
+ }
+ }
+
+ if (error.keyword === 'additionalProperties') {
+ error.message = 'should NOT have additional property: ' + error.params.additionalProperty;
+ }
+
+ return error;
+};
+
+/**
+ * Test whether something is a Promise
+ * @param {*} object
+ * @returns {boolean} Returns true when object is a promise, false otherwise
+ */
+exports.isPromise = function (object) {
+ return object && typeof object.then === 'function' && typeof object.catch === 'function';
+};
+
+/**
+ * Test whether a custom validation error has the correct structure
+ * @param {*} validationError The error to be checked.
+ * @returns {boolean} Returns true if the structure is ok, false otherwise
+ */
+exports.isValidValidationError = function (validationError) {
+ return typeof validationError === 'object' &&
+ Array.isArray(validationError.path) &&
+ typeof validationError.message === 'string';
+};
+
+/**
+ * Test whether the child rect fits completely inside the parent rect.
+ * @param {ClientRect} parent
+ * @param {ClientRect} child
+ * @param {number} margin
+ */
+exports.insideRect = function (parent, child, margin) {
+ var _margin = margin !== undefined ? margin : 0;
+ return child.left - _margin >= parent.left
+ && child.right + _margin <= parent.right
+ && child.top - _margin >= parent.top
+ && child.bottom + _margin <= parent.bottom;
+};
+
+/**
+ * Returns a function, that, as long as it continues to be invoked, will not
+ * be triggered. The function will be called after it stops being called for
+ * N milliseconds.
+ *
+ * Source: https://davidwalsh.name/javascript-debounce-function
+ *
+ * @param {function} func
+ * @param {number} wait Number in milliseconds
+ * @param {boolean} [immediate=false] If `immediate` is passed, trigger the
+ * function on the leading edge, instead
+ * of the trailing.
+ * @return {function} Return the debounced function
+ */
+exports.debounce = function debounce(func, wait, immediate) {
+ var timeout;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) func.apply(context, args);
+ };
+ var callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) func.apply(context, args);
+ };
+};
+
+/**
+ * Determines the difference between two texts.
+ * Can only detect one removed or inserted block of characters.
+ * @param {string} oldText
+ * @param {string} newText
+ * @return {{start: number, end: number}} Returns the start and end
+ * of the changed part in newText.
+ */
+exports.textDiff = function textDiff(oldText, newText) {
+ var len = newText.length;
+ var start = 0;
+ var oldEnd = oldText.length;
+ var newEnd = newText.length;
+
+ while (newText.charAt(start) === oldText.charAt(start)
+ && start < len) {
+ start++;
+ }
+
+ while (newText.charAt(newEnd - 1) === oldText.charAt(oldEnd - 1)
+ && newEnd > start && oldEnd > 0) {
+ newEnd--;
+ oldEnd--;
+ }
+
+ return {start: start, end: newEnd};
+};
+
+
+/**
+ * Return an object with the selection range or cursor position (if both have the same value)
+ * Support also old browsers (IE8-)
+ * Source: http://ourcodeworld.com/articles/read/282/how-to-get-the-current-cursor-position-and-selection-within-a-text-input-or-textarea-in-javascript
+ * @param {DOMElement} el A dom element of a textarea or input text.
+ * @return {Object} reference Object with 2 properties (start and end) with the identifier of the location of the cursor and selected text.
+ **/
+exports.getInputSelection = function(el) {
+ var startIndex = 0, endIndex = 0, normalizedValue, range, textInputRange, len, endRange;
+
+ if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
+ startIndex = el.selectionStart;
+ endIndex = el.selectionEnd;
+ } else {
+ range = document.selection.createRange();
+
+ if (range && range.parentElement() == el) {
+ len = el.value.length;
+ normalizedValue = el.value.replace(/\r\n/g, "\n");
+
+ // Create a working TextRange that lives only in the input
+ textInputRange = el.createTextRange();
+ textInputRange.moveToBookmark(range.getBookmark());
+
+ // Check if the startIndex and endIndex of the selection are at the very end
+ // of the input, since moveStart/moveEnd doesn't return what we want
+ // in those cases
+ endRange = el.createTextRange();
+ endRange.collapse(false);
+
+ if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
+ startIndex = endIndex = len;
+ } else {
+ startIndex = -textInputRange.moveStart("character", -len);
+ startIndex += normalizedValue.slice(0, startIndex).split("\n").length - 1;
+
+ if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
+ endIndex = len;
+ } else {
+ endIndex = -textInputRange.moveEnd("character", -len);
+ endIndex += normalizedValue.slice(0, endIndex).split("\n").length - 1;
+ }
+ }
+ }
+ }
+
+ return {
+ startIndex: startIndex,
+ endIndex: endIndex,
+ start: _positionForIndex(startIndex),
+ end: _positionForIndex(endIndex)
+ };
+
+ /**
+ * Returns textarea row and column position for certain index
+ * @param {Number} index text index
+ * @returns {{row: Number, col: Number}}
+ */
+ function _positionForIndex(index) {
+ var textTillIndex = el.value.substring(0,index);
+ var row = (textTillIndex.match(/\n/g) || []).length + 1;
+ var col = textTillIndex.length - textTillIndex.lastIndexOf("\n");
+
+ return {
+ row: row,
+ column: col
+ }
+ }
+}
+
+/**
+ * Returns the index for certaion position in text element
+ * @param {DOMElement} el A dom element of a textarea or input text.
+ * @param {Number} row row value, > 0, if exceeds rows number - last row will be returned
+ * @param {Number} column column value, > 0, if exceeds column length - end of column will be returned
+ * @returns {Number} index of position in text, -1 if not found
+ */
+exports.getIndexForPosition = function(el, row, column) {
+ var text = el.value || '';
+ if (row > 0 && column > 0) {
+ var rows = text.split('\n', row);
+ row = Math.min(rows.length, row);
+ column = Math.min(rows[row - 1].length, column - 1);
+ var columnCount = (row == 1 ? column : column + 1); // count new line on multiple rows
+ return rows.slice(0, row - 1).join('\n').length + columnCount;
+ }
+ return -1;
+}
+
+/**
+ * Returns location of json paths in certain json string
+ * @param {String} text json string
+ * @param {Array} paths array of json paths
+ * @returns {Array<{path: String, line: Number, row: Number}>}
+ */
+exports.getPositionForPath = function(text, paths) {
+ var me = this;
+ var result = [];
+ var jsmap;
+ if (!paths || !paths.length) {
+ return result;
+ }
+
+ try {
+ jsmap = jsonMap.parse(text);
+ } catch (err) {
+ return result;
+ }
+
+ paths.forEach(function (path) {
+ var pathArr = me.parsePath(path);
+ var pointerName = pathArr.length ? "/" + pathArr.join("/") : "";
+ var pointer = jsmap.pointers[pointerName];
+ if (pointer) {
+ result.push({
+ path: path,
+ line: pointer.key ? pointer.key.line : (pointer.value ? pointer.value.line : 0),
+ column: pointer.key ? pointer.key.column : (pointer.value ? pointer.value.column : 0)
+ });
+ }
+ });
+
+ return result;
+
+}
+
+/**
+ * Get the applied color given a color name or code
+ * Source: https://stackoverflow.com/questions/6386090/validating-css-color-names/33184805
+ * @param {string} color
+ * @returns {string | null} returns the color if the input is a valid
+ * color, and returns null otherwise. Example output:
+ * 'rgba(255,0,0,0.7)' or 'rgb(255,0,0)'
+ */
+exports.getColorCSS = function (color) {
+ var ele = document.createElement('div');
+ ele.style.color = color;
+ return ele.style.color.split(/\s+/).join('').toLowerCase() || null;
+}
+
+/**
+ * Test if a string contains a valid color name or code.
+ * @param {string} color
+ * @returns {boolean} returns true if a valid color, false otherwise
+ */
+exports.isValidColor = function (color) {
+ return !!exports.getColorCSS(color);
+}
+
+/**
+ * Make a tooltip for a field based on the field's schema.
+ * @param {object} schema JSON schema
+ * @param {string} [locale] Locale code (for example, zh-CN)
+ * @returns {string} Field tooltip, may be empty string if all relevant schema properties are missing
+ */
+exports.makeFieldTooltip = function (schema, locale) {
+ if (!schema) {
+ return '';
+ }
+
+ var tooltip = '';
+ if (schema.title) {
+ tooltip += schema.title;
+ }
+
+ if (schema.description) {
+ if (tooltip.length > 0) {
+ tooltip += '\n';
+ }
+ tooltip += schema.description;
+ }
+
+ if (schema.default) {
+ if (tooltip.length > 0) {
+ tooltip += '\n\n';
+ }
+ tooltip += translate('default', undefined, locale) + '\n';
+ tooltip += JSON.stringify(schema.default, null, 2);
+ }
+
+ if (Array.isArray(schema.examples) && schema.examples.length > 0) {
+ if (tooltip.length > 0) {
+ tooltip += '\n\n';
+ }
+ tooltip += translate('examples', undefined, locale) + '\n';
+ schema.examples.forEach(function (example, index) {
+ tooltip += JSON.stringify(example, null, 2);
+ if (index !== schema.examples.length - 1) {
+ tooltip += '\n';
+ }
+ });
+ }
+
+ return tooltip;
+}
+
+/**
+ * Get a nested property from an object.
+ * Returns undefined when the property does not exist.
+ * @param {Object} object
+ * @param {string[]} path
+ * @return {*}
+ */
+exports.get = function (object, path) {
+ var value = object
+
+ for (var i = 0; i < path.length && value !== undefined && value !== null; i++) {
+ value = value[path[i]]
+ }
+
+ return value;
+}
+
+/**
+ * Find a unique name. Suffix the name with ' (copy)', '(copy 2)', etc
+ * until a unique name is found
+ * @param {string} name
+ * @param {Array} existingPropNames Array with existing prop names
+ */
+exports.findUniqueName = function(name, existingPropNames) {
+ var strippedName = name.replace(/ \(copy( \d+)?\)$/, '')
+ var validName = strippedName
+ var i = 1
+
+ while (existingPropNames.indexOf(validName) !== -1) {
+ var copy = 'copy' + (i > 1 ? (' ' + i) : '')
+ validName = strippedName + ' (' + copy + ')'
+ i++
+ }
+
+ return validName
+}
+
+/**
+ * Get the child paths of an array
+ * @param {JSON} json
+ * @param {boolean} [includeObjects=false] If true, object and array paths are returned as well
+ * @return {string[]}
+ */
+exports.getChildPaths = function (json, includeObjects) {
+ var pathsMap = {};
+
+ function getObjectChildPaths (json, pathsMap, rootPath, includeObjects) {
+ var isValue = !Array.isArray(json) && !exports.isObject(json)
+
+ if (isValue || includeObjects) {
+ pathsMap[rootPath || ''] = true;
+ }
+
+ if (exports.isObject(json)) {
+ Object.keys(json).forEach(function (field) {
+ getObjectChildPaths(json[field], pathsMap, rootPath + '.' + field, includeObjects);
+ });
+ }
+ }
+
+ if (Array.isArray(json)) {
+ var max = Math.min(json.length, MAX_ITEMS_FIELDS_COLLECTION);
+ for (var i = 0; i < max; i++) {
+ var item = json[i];
+ getObjectChildPaths(item, pathsMap, '', includeObjects);
+ }
+ }
+ else {
+ pathsMap[''] = true;
+ }
+
+ return Object.keys(pathsMap).sort();
+}
+
+/**
+ * Sort object keys using natural sort
+ * @param {Array} array
+ * @param {String} [path] JSON pointer
+ * @param {'asc' | 'desc'} [direction]
+ */
+exports.sort = function (array, path, direction) {
+ var parsedPath = path && path !== '.' ? exports.parsePath(path) : []
+ var sign = direction === 'desc' ? -1: 1
+
+ var sortedArray = array.slice()
+ sortedArray.sort(function (a, b) {
+ var aValue = exports.get(a, parsedPath);
+ var bValue = exports.get(b, parsedPath);
+
+ return sign * (aValue > bValue ? 1 : aValue < bValue ? -1 : 0);
+ })
+
+ return sortedArray;
+}
+
+/**
+ * Sort object keys using natural sort
+ * @param {Object} object
+ * @param {'asc' | 'desc'} [direction]
+ */
+exports.sortObjectKeys = function (object, direction) {
+ var sign = (direction === 'desc') ? -1 : 1;
+ var sortedFields = Object.keys(object).sort(function (a, b) {
+ return sign * naturalSort(a, b);
+ });
+
+ var sortedObject = {};
+ sortedFields.forEach(function (field) {
+ sortedObject[field] = object[field];
+ });
+
+ return sortedObject;
+}
+
+/**
+ * Cast contents of a string to the correct type.
+ * This can be a string, a number, a boolean, etc
+ * @param {String} str
+ * @return {*} castedStr
+ * @private
+ */
+exports.parseString = function(str) {
+ var lower = str.toLowerCase();
+ var num = Number(str); // will nicely fail with '123ab'
+ var numFloat = parseFloat(str); // will nicely fail with ' '
+
+ if (str === '') {
+ return '';
+ }
+ else if (lower === 'null') {
+ return null;
+ }
+ else if (lower === 'true') {
+ return true;
+ }
+ else if (lower === 'false') {
+ return false;
+ }
+ else if (!isNaN(num) && !isNaN(numFloat)) {
+ return num;
+ }
+ else {
+ return str;
+ }
+};
+
+/**
+ * Return a human readable document size
+ * For example formatSize(7570718) outputs '7.2 MiB'
+ * @param {number} size
+ * @return {string} Returns a human readable size
+ */
+exports.formatSize = function (size) {
+ if (size < 900) {
+ return size.toFixed() + ' B';
+ }
+
+ var KiB = size / 1024;
+ if (KiB < 900) {
+ return KiB.toFixed(1) + ' KiB';
+ }
+
+ var MiB = KiB / 1024;
+ if (MiB < 900) {
+ return MiB.toFixed(1) + ' MiB';
+ }
+
+ var GiB = MiB / 1024;
+ if (GiB < 900) {
+ return GiB.toFixed(1) + ' GiB';
+ }
+
+ var TiB = GiB / 1024;
+ return TiB.toFixed(1) + ' TiB';
+}
+
+/**
+ * Limit text to a maximum number of characters
+ * @param {string} text
+ * @param {number} maxCharacterCount
+ * @return {string} Returns the limited text,
+ * ending with '...' if the max was exceeded
+ */
+exports.limitCharacters = function (text, maxCharacterCount) {
+ if (text.length <= maxCharacterCount) {
+ return text;
+ }
+
+ return text.slice(0, maxCharacterCount) + '...';
+}
+
+/**
+ * Test whether a value is an Object
+ * @param {*} value
+ * @return {boolean}
+ */
+exports.isObject = function (value) {
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
+}
+
+/**
+ * Helper function to test whether an array contains an item
+ * @param {Array} array
+ * @param {*} item
+ * @return {boolean} Returns true if `item` is in `array`, returns false otherwise.
+ */
+exports.contains = function (array, item) {
+ return array.indexOf(item) !== -1;
+}
/***/ }),
@@ -1571,451 +1571,451 @@ exports.contains = function (array, item) {
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-
-
-__webpack_require__(23);
-
-var _locales = ['en', 'pt-BR', 'zh-CN', 'tr'];
-var _defs = {
- en: {
- array: 'Array',
- auto: 'Auto',
- appendText: 'Append',
- appendTitle: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)',
- appendSubmenuTitle: 'Select the type of the field to be appended',
- appendTitleAuto: 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)',
- ascending: 'Ascending',
- ascendingTitle: 'Sort the childs of this ${type} in ascending order',
- actionsMenu: 'Click to open the actions menu (Ctrl+M)',
- collapseAll: 'Collapse all fields',
- descending: 'Descending',
- descendingTitle: 'Sort the childs of this ${type} in descending order',
- drag: 'Drag to move this field (Alt+Shift+Arrows)',
- duplicateKey: 'duplicate key',
- duplicateText: 'Duplicate',
- duplicateTitle: 'Duplicate selected fields (Ctrl+D)',
- duplicateField: 'Duplicate this field (Ctrl+D)',
- duplicateFieldError: 'Duplicate field name',
- cannotParseFieldError: 'Cannot parse field into JSON',
- cannotParseValueError: 'Cannot parse value into JSON',
- empty: 'empty',
- expandAll: 'Expand all fields',
- expandTitle: 'Click to expand/collapse this field (Ctrl+E). \n' +
- 'Ctrl+Click to expand/collapse including all childs.',
- insert: 'Insert',
- insertTitle: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)',
- insertSub: 'Select the type of the field to be inserted',
- object: 'Object',
- ok: 'Ok',
- redo: 'Redo (Ctrl+Shift+Z)',
- removeText: 'Remove',
- removeTitle: 'Remove selected fields (Ctrl+Del)',
- removeField: 'Remove this field (Ctrl+Del)',
- selectNode: 'Select a node...',
- showAll: 'show all',
- showMore: 'show more',
- showMoreStatus: 'displaying ${visibleChilds} of ${totalChilds} items.',
- sort: 'Sort',
- sortTitle: 'Sort the childs of this ${type}',
- sortTitleShort: 'Sort contents',
- sortFieldLabel: 'Field:',
- sortDirectionLabel: 'Direction:',
- sortFieldTitle: 'Select the nested field by which to sort the array or object',
- sortAscending: 'Ascending',
- sortAscendingTitle: 'Sort the selected field in ascending order',
- sortDescending: 'Descending',
- sortDescendingTitle: 'Sort the selected field in descending order',
- string: 'String',
- transform: 'Transform',
- transformTitle: 'Filter, sort, or transform the childs of this ${type}',
- transformTitleShort: 'Filter, sort, or transform contents',
- extract: 'Extract',
- extractTitle: 'Extract this ${type}',
- transformQueryTitle: 'Enter a JMESPath query',
- transformWizardLabel: 'Wizard',
- transformWizardFilter: 'Filter',
- transformWizardSortBy: 'Sort by',
- transformWizardSelectFields: 'Select fields',
- transformQueryLabel: 'Query',
- transformPreviewLabel: 'Preview',
- type: 'Type',
- typeTitle: 'Change the type of this field',
- openUrl: 'Ctrl+Click or Ctrl+Enter to open url in new window',
- undo: 'Undo last action (Ctrl+Z)',
- validationCannotMove: 'Cannot move a field into a child of itself',
- autoType: 'Field type "auto". ' +
- 'The field type is automatically determined from the value ' +
- 'and can be a string, number, boolean, or null.',
- objectType: 'Field type "object". ' +
- 'An object contains an unordered set of key/value pairs.',
- arrayType: 'Field type "array". ' +
- 'An array contains an ordered collection of values.',
- stringType: 'Field type "string". ' +
- 'Field type is not determined from the value, ' +
- 'but always returned as string.',
- modeCodeText: 'Code',
- modeCodeTitle: 'Switch to code highlighter',
- modeFormText: 'Form',
- modeFormTitle: 'Switch to form editor',
- modeTextText: 'Text',
- modeTextTitle: 'Switch to plain text editor',
- modeTreeText: 'Tree',
- modeTreeTitle: 'Switch to tree editor',
- modeViewText: 'View',
- modeViewTitle: 'Switch to tree view',
- modePreviewText: 'Preview',
- modePreviewTitle: 'Switch to preview mode',
- examples: 'Examples',
- default: 'Default',
- },
- 'zh-CN': {
- array: '数组',
- auto: '自动',
- appendText: '追加',
- appendTitle: '在此字段后追加一个类型为“auto”的新字段 (Ctrl+Shift+Ins)',
- appendSubmenuTitle: '选择要追加的字段类型',
- appendTitleAuto: '追加类型为“auto”的新字段 (Ctrl+Shift+Ins)',
- ascending: '升序',
- ascendingTitle: '升序排列${type}的子节点',
- actionsMenu: '点击打开动作菜单(Ctrl+M)',
- collapseAll: '缩进所有字段',
- descending: '降序',
- descendingTitle: '降序排列${type}的子节点',
- drag: '拖拽移动该节点(Alt+Shift+Arrows)',
- duplicateKey: '重复键',
- duplicateText: '复制',
- duplicateTitle: '复制选中字段(Ctrl+D)',
- duplicateField: '复制该字段(Ctrl+D)',
- duplicateFieldError: '重复的字段名称',
- cannotParseFieldError: '无法将字段解析为JSON',
- cannotParseValueError: '无法将值解析为JSON',
- empty: '清空',
- expandAll: '展开所有字段',
- expandTitle: '点击 展开/收缩 该字段(Ctrl+E). \n' +
- 'Ctrl+Click 展开/收缩 包含所有子节点.',
- insert: '插入',
- insertTitle: '在此字段前插入类型为“auto”的新字段 (Ctrl+Ins)',
- insertSub: '选择要插入的字段类型',
- object: '对象',
- ok: 'Ok',
- redo: '重做 (Ctrl+Shift+Z)',
- removeText: '移除',
- removeTitle: '移除选中字段 (Ctrl+Del)',
- removeField: '移除该字段 (Ctrl+Del)',
- selectNode: '选择一个节点...',
- showAll: '展示全部',
- showMore: '展示更多',
- showMoreStatus: '显示${totalChilds}的${visibleChilds}项目.',
- sort: '排序',
- sortTitle: '排序${type}的子节点',
- sortTitleShort: '内容排序',
- sortFieldLabel: '字段:',
- sortDirectionLabel: '方向:',
- sortFieldTitle: '选择用于对数组或对象排序的嵌套字段',
- sortAscending: '升序排序',
- sortAscendingTitle: '按照该字段升序排序',
- sortDescending: '降序排序',
- sortDescendingTitle: '按照该字段降序排序',
- string: '字符串',
- transform: '变换',
- transformTitle: '筛选,排序,或者转换${type}的子节点',
- transformTitleShort: '筛选,排序,或者转换内容',
- extract: '提取',
- extractTitle: '提取这个 ${type}',
- transformQueryTitle: '输入JMESPath查询',
- transformWizardLabel: '向导',
- transformWizardFilter: '筛选',
- transformWizardSortBy: '排序',
- transformWizardSelectFields: '选择字段',
- transformQueryLabel: '查询',
- transformPreviewLabel: '预览',
- type: '类型',
- typeTitle: '更改字段类型',
- openUrl: 'Ctrl+Click 或者 Ctrl+Enter 在新窗口打开链接',
- undo: '撤销上次动作 (Ctrl+Z)',
- validationCannotMove: '无法将字段移入其子节点',
- autoType: '字段类型 "auto". ' +
- '字段类型由值自动确定 ' +
- '可以为 string,number,boolean,或者 null.',
- objectType: '字段类型 "object". ' +
- '对象包含一组无序的键/值对.',
- arrayType: '字段类型 "array". ' +
- '数组包含值的有序集合.',
- stringType: '字段类型 "string". ' +
- '字段类型由值自动确定,' +
- '但始终作为字符串返回.',
- modeCodeText: '代码',
- modeCodeTitle: '切换至代码高亮',
- modeFormText: '表单',
- modeFormTitle: '切换至表单编辑',
- modeTextText: '文本',
- modeTextTitle: '切换至文本编辑',
- modeTreeText: '树',
- modeTreeTitle: '切换至树编辑',
- modeViewText: '视图',
- modeViewTitle: '切换至树视图',
- modePreviewText: '预览',
- modePreviewTitle: '切换至预览模式',
- examples: '例子',
- default: '缺省',
- },
- 'pt-BR': {
- array: 'Lista',
- auto: 'Automatico',
- appendText: 'Adicionar',
- appendTitle: 'Adicionar novo campo com tipo \'auto\' depois deste campo (Ctrl+Shift+Ins)',
- appendSubmenuTitle: 'Selecione o tipo do campo a ser adicionado',
- appendTitleAuto: 'Adicionar novo campo com tipo \'auto\' (Ctrl+Shift+Ins)',
- ascending: 'Ascendente',
- ascendingTitle: 'Organizar filhor do tipo ${type} em crescente',
- actionsMenu: 'Clique para abrir o menu de ações (Ctrl+M)',
- collapseAll: 'Fechar todos campos',
- descending: 'Descendente',
- descendingTitle: 'Organizar o filhos do tipo ${type} em decrescente',
- duplicateKey: 'chave duplicada',
- drag: 'Arraste para mover este campo (Alt+Shift+Arrows)',
- duplicateText: 'Duplicar',
- duplicateTitle: 'Duplicar campos selecionados (Ctrl+D)',
- duplicateField: 'Duplicar este campo (Ctrl+D)',
- duplicateFieldError: 'Nome do campo duplicado',
- cannotParseFieldError: 'Não é possível analisar o campo no JSON',
- cannotParseValueError: 'Não é possível analisar o valor em JSON',
- empty: 'vazio',
- expandAll: 'Expandir todos campos',
- expandTitle: 'Clique para expandir/encolher este campo (Ctrl+E). \n' +
- 'Ctrl+Click para expandir/encolher incluindo todos os filhos.',
- insert: 'Inserir',
- insertTitle: 'Inserir um novo campo do tipo \'auto\' antes deste campo (Ctrl+Ins)',
- insertSub: 'Selecionar o tipo de campo a ser inserido',
- object: 'Objeto',
- ok: 'Ok',
- redo: 'Refazer (Ctrl+Shift+Z)',
- removeText: 'Remover',
- removeTitle: 'Remover campos selecionados (Ctrl+Del)',
- removeField: 'Remover este campo (Ctrl+Del)',
- // TODO: correctly translate
- selectNode: 'Select a node...',
- // TODO: correctly translate
- showAll: 'mostre tudo',
- // TODO: correctly translate
- showMore: 'mostre mais',
- // TODO: correctly translate
- showMoreStatus: 'exibindo ${visibleChilds} de ${totalChilds} itens.',
- sort: 'Organizar',
- sortTitle: 'Organizar os filhos deste ${type}',
- // TODO: correctly translate
- sortTitleShort: 'Organizar os filhos',
- // TODO: correctly translate
- sortFieldLabel: 'Field:',
- // TODO: correctly translate
- sortDirectionLabel: 'Direction:',
- // TODO: correctly translate
- sortFieldTitle: 'Select the nested field by which to sort the array or object',
- // TODO: correctly translate
- sortAscending: 'Ascending',
- // TODO: correctly translate
- sortAscendingTitle: 'Sort the selected field in ascending order',
- // TODO: correctly translate
- sortDescending: 'Descending',
- // TODO: correctly translate
- sortDescendingTitle: 'Sort the selected field in descending order',
- string: 'Texto',
- // TODO: correctly translate
- transform: 'Transform',
- // TODO: correctly translate
- transformTitle: 'Filter, sort, or transform the childs of this ${type}',
- // TODO: correctly translate
- transformTitleShort: 'Filter, sort, or transform contents',
- // TODO: correctly translate
- transformQueryTitle: 'Enter a JMESPath query',
- // TODO: correctly translate
- transformWizardLabel: 'Wizard',
- // TODO: correctly translate
- transformWizardFilter: 'Filter',
- // TODO: correctly translate
- transformWizardSortBy: 'Sort by',
- // TODO: correctly translate
- transformWizardSelectFields: 'Select fields',
- // TODO: correctly translate
- transformQueryLabel: 'Query',
- // TODO: correctly translate
- transformPreviewLabel: 'Preview',
- type: 'Tipo',
- typeTitle: 'Mudar o tipo deste campo',
- openUrl: 'Ctrl+Click ou Ctrl+Enter para abrir link em nova janela',
- undo: 'Desfazer último ação (Ctrl+Z)',
- validationCannotMove: 'Não pode mover um campo como filho dele mesmo',
- autoType: 'Campo do tipo "auto". ' +
- 'O tipo do campo é determinao automaticamente a partir do seu valor ' +
- 'e pode ser texto, número, verdade/falso ou nulo.',
- objectType: 'Campo do tipo "objeto". ' +
- 'Um objeto contém uma lista de pares com chave e valor.',
- arrayType: 'Campo do tipo "lista". ' +
- 'Uma lista contem uma coleção de valores ordenados.',
- stringType: 'Campo do tipo "string". ' +
- 'Campo do tipo nao é determinado através do seu valor, ' +
- 'mas sempre retornara um texto.',
- examples: 'Exemplos',
- default: 'Revelia',
- },
- tr: {
- array: 'Dizin',
- auto: 'Otomatik',
- appendText: 'Ekle',
- appendTitle: 'Bu alanın altına \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)',
- appendSubmenuTitle: 'Eklenecek alanın tipini seç',
- appendTitleAuto: '\'Otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)',
- ascending: 'Artan',
- ascendingTitle: '${type}\'ın alt tiplerini artan düzende sırala',
- actionsMenu: 'Aksiyon menüsünü açmak için tıklayın (Ctrl+M)',
- collapseAll: 'Tüm alanları kapat',
- descending: 'Azalan',
- descendingTitle: '${type}\'ın alt tiplerini azalan düzende sırala',
- drag: 'Bu alanı taşımak için sürükleyin (Alt+Shift+Arrows)',
- duplicateKey: 'Var olan anahtar',
- duplicateText: 'Aşağıya kopyala',
- duplicateTitle: 'Seçili alanlardan bir daha oluştur (Ctrl+D)',
- duplicateField: 'Bu alandan bir daha oluştur (Ctrl+D)',
- duplicateFieldError: 'Duplicate field name',
- cannotParseFieldError: 'Alan JSON\'a ayrıştırılamıyor',
- cannotParseValueError: 'JSON\'a değer ayrıştırılamıyor',
- empty: 'boş',
- expandAll: 'Tüm alanları aç',
- expandTitle: 'Bu alanı açmak/kapatmak için tıkla (Ctrl+E). \n' +
- 'Alt alanlarda dahil tüm alanları açmak için Ctrl+Click ',
- insert: 'Ekle',
- insertTitle: 'Bu alanın üstüne \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Ins)',
- insertSub: 'Araya eklenecek alanın tipini seç',
- object: 'Nesne',
- ok: 'Tamam',
- redo: 'Yeniden yap (Ctrl+Shift+Z)',
- removeText: 'Kaldır',
- removeTitle: 'Seçilen alanları kaldır (Ctrl+Del)',
- removeField: 'Bu alanı kaldır (Ctrl+Del)',
- selectNode: 'Bir nesne seç...',
- showAll: 'tümünü göster',
- showMore: 'daha fazla göster',
- showMoreStatus: '${totalChilds} alanın ${visibleChilds} alt alanları gösteriliyor',
- sort: 'Sırala',
- sortTitle: '${type}\'ın alt alanlarını sırala',
- sortTitleShort: 'İçerikleri sırala',
- sortFieldLabel: 'Alan:',
- sortDirectionLabel: 'Yön:',
- sortFieldTitle: 'Diziyi veya nesneyi sıralamak için iç içe geçmiş alanı seçin',
- sortAscending: 'Artan',
- sortAscendingTitle: 'Seçili alanı artan düzende sırala',
- sortDescending: 'Azalan',
- sortDescendingTitle: 'Seçili alanı azalan düzende sırala',
- string: 'Karakter Dizisi',
- transform: 'Dönüştür',
- transformTitle: '${type}\'ın alt alanlarını filtrele, sırala veya dönüştür',
- transformTitleShort: 'İçerikleri filterele, sırala veya dönüştür',
- transformQueryTitle: 'JMESPath sorgusu gir',
- transformWizardLabel: 'Sihirbaz',
- transformWizardFilter: 'Filtre',
- transformWizardSortBy: 'Sırala',
- transformWizardSelectFields: 'Alanları seç',
- transformQueryLabel: 'Sorgu',
- transformPreviewLabel: 'Önizleme',
- type: 'Tip',
- typeTitle: 'Bu alanın tipini değiştir',
- openUrl: 'URL\'i yeni bir pencerede açmak için Ctrl+Click veya Ctrl+Enter',
- undo: 'Son değişikliği geri al (Ctrl+Z)',
- validationCannotMove: 'Alt alan olarak taşınamıyor',
- autoType: 'Alan tipi "otomatik". ' +
- 'Alan türü otomatik olarak değerden belirlenir' +
- 've bir dize, sayı, boolean veya null olabilir.',
- objectType: 'Alan tipi "nesne". ' +
- 'Bir nesne, sıralanmamış bir anahtar / değer çifti kümesi içerir.',
- arrayType: 'Alan tipi "dizi". ' +
- 'Bir dizi, düzenli değerler koleksiyonu içerir.',
- stringType: 'Alan tipi "karakter dizisi". ' +
- 'Alan türü değerden belirlenmez,' +
- 'ancak her zaman karakter dizisi olarak döndürülür.',
- modeCodeText: 'Kod',
- modeCodeTitle: 'Kod vurgulayıcıya geç',
- modeFormText: 'Form',
- modeFormTitle: 'Form düzenleyiciye geç',
- modeTextText: 'Metin',
- modeTextTitle: 'Düz metin düzenleyiciye geç',
- modeTreeText: 'Ağaç',
- modeTreeTitle: 'Ağaç düzenleyiciye geç',
- modeViewText: 'Görünüm',
- modeViewTitle: 'Ağaç görünümüne geç',
- examples: 'Örnekler',
- default: 'Varsayılan',
- }
-};
-
-var _defaultLang = 'en';
-var _lang;
-var userLang = typeof navigator !== 'undefined' ?
- navigator.language || navigator.userLanguage :
- undefined;
-_lang = _locales.find(function (l) {
- return l === userLang;
-});
-if (!_lang) {
- _lang = _defaultLang;
-}
-
-module.exports = {
- // supported locales
- _locales: _locales,
- _defs: _defs,
- _lang: _lang,
- setLanguage: function (lang) {
- if (!lang) {
- return;
- }
- var langFound = _locales.find(function (l) {
- return l === lang;
- });
- if (langFound) {
- _lang = langFound;
- } else {
- console.error('Language not found');
- }
- },
- setLanguages: function (languages) {
- if (!languages) {
- return;
- }
- for (var key in languages) {
- var langFound = _locales.find(function (l) {
- return l === key;
- });
- if (!langFound) {
- _locales.push(key);
- }
- _defs[key] = Object.assign({}, _defs[_defaultLang], _defs[key], languages[key]);
- }
- },
- translate: function (key, data, lang) {
- if (!lang) {
- lang = _lang;
- }
- var text = _defs[lang][key];
- if (data) {
- for (key in data) {
- text = text.replace('${' + key + '}', data[key]);
- }
- }
- return text || key;
- }
+
+
+__webpack_require__(23);
+
+var _locales = ['en', 'pt-BR', 'zh-CN', 'tr'];
+var _defs = {
+ en: {
+ array: 'Array',
+ auto: 'Auto',
+ appendText: 'Append',
+ appendTitle: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)',
+ appendSubmenuTitle: 'Select the type of the field to be appended',
+ appendTitleAuto: 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)',
+ ascending: 'Ascending',
+ ascendingTitle: 'Sort the childs of this ${type} in ascending order',
+ actionsMenu: 'Click to open the actions menu (Ctrl+M)',
+ collapseAll: 'Collapse all fields',
+ descending: 'Descending',
+ descendingTitle: 'Sort the childs of this ${type} in descending order',
+ drag: 'Drag to move this field (Alt+Shift+Arrows)',
+ duplicateKey: 'duplicate key',
+ duplicateText: 'Duplicate',
+ duplicateTitle: 'Duplicate selected fields (Ctrl+D)',
+ duplicateField: 'Duplicate this field (Ctrl+D)',
+ duplicateFieldError: 'Duplicate field name',
+ cannotParseFieldError: 'Cannot parse field into JSON',
+ cannotParseValueError: 'Cannot parse value into JSON',
+ empty: 'empty',
+ expandAll: 'Expand all fields',
+ expandTitle: 'Click to expand/collapse this field (Ctrl+E). \n' +
+ 'Ctrl+Click to expand/collapse including all childs.',
+ insert: 'Insert',
+ insertTitle: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)',
+ insertSub: 'Select the type of the field to be inserted',
+ object: 'Object',
+ ok: 'Ok',
+ redo: 'Redo (Ctrl+Shift+Z)',
+ removeText: 'Remove',
+ removeTitle: 'Remove selected fields (Ctrl+Del)',
+ removeField: 'Remove this field (Ctrl+Del)',
+ selectNode: 'Select a node...',
+ showAll: 'show all',
+ showMore: 'show more',
+ showMoreStatus: 'displaying ${visibleChilds} of ${totalChilds} items.',
+ sort: 'Sort',
+ sortTitle: 'Sort the childs of this ${type}',
+ sortTitleShort: 'Sort contents',
+ sortFieldLabel: 'Field:',
+ sortDirectionLabel: 'Direction:',
+ sortFieldTitle: 'Select the nested field by which to sort the array or object',
+ sortAscending: 'Ascending',
+ sortAscendingTitle: 'Sort the selected field in ascending order',
+ sortDescending: 'Descending',
+ sortDescendingTitle: 'Sort the selected field in descending order',
+ string: 'String',
+ transform: 'Transform',
+ transformTitle: 'Filter, sort, or transform the childs of this ${type}',
+ transformTitleShort: 'Filter, sort, or transform contents',
+ extract: 'Extract',
+ extractTitle: 'Extract this ${type}',
+ transformQueryTitle: 'Enter a JMESPath query',
+ transformWizardLabel: 'Wizard',
+ transformWizardFilter: 'Filter',
+ transformWizardSortBy: 'Sort by',
+ transformWizardSelectFields: 'Select fields',
+ transformQueryLabel: 'Query',
+ transformPreviewLabel: 'Preview',
+ type: 'Type',
+ typeTitle: 'Change the type of this field',
+ openUrl: 'Ctrl+Click or Ctrl+Enter to open url in new window',
+ undo: 'Undo last action (Ctrl+Z)',
+ validationCannotMove: 'Cannot move a field into a child of itself',
+ autoType: 'Field type "auto". ' +
+ 'The field type is automatically determined from the value ' +
+ 'and can be a string, number, boolean, or null.',
+ objectType: 'Field type "object". ' +
+ 'An object contains an unordered set of key/value pairs.',
+ arrayType: 'Field type "array". ' +
+ 'An array contains an ordered collection of values.',
+ stringType: 'Field type "string". ' +
+ 'Field type is not determined from the value, ' +
+ 'but always returned as string.',
+ modeCodeText: 'Code',
+ modeCodeTitle: 'Switch to code highlighter',
+ modeFormText: 'Form',
+ modeFormTitle: 'Switch to form editor',
+ modeTextText: 'Text',
+ modeTextTitle: 'Switch to plain text editor',
+ modeTreeText: 'Tree',
+ modeTreeTitle: 'Switch to tree editor',
+ modeViewText: 'View',
+ modeViewTitle: 'Switch to tree view',
+ modePreviewText: 'Preview',
+ modePreviewTitle: 'Switch to preview mode',
+ examples: 'Examples',
+ default: 'Default',
+ },
+ 'zh-CN': {
+ array: '数组',
+ auto: '自动',
+ appendText: '追加',
+ appendTitle: '在此字段后追加一个类型为“auto”的新字段 (Ctrl+Shift+Ins)',
+ appendSubmenuTitle: '选择要追加的字段类型',
+ appendTitleAuto: '追加类型为“auto”的新字段 (Ctrl+Shift+Ins)',
+ ascending: '升序',
+ ascendingTitle: '升序排列${type}的子节点',
+ actionsMenu: '点击打开动作菜单(Ctrl+M)',
+ collapseAll: '缩进所有字段',
+ descending: '降序',
+ descendingTitle: '降序排列${type}的子节点',
+ drag: '拖拽移动该节点(Alt+Shift+Arrows)',
+ duplicateKey: '重复键',
+ duplicateText: '复制',
+ duplicateTitle: '复制选中字段(Ctrl+D)',
+ duplicateField: '复制该字段(Ctrl+D)',
+ duplicateFieldError: '重复的字段名称',
+ cannotParseFieldError: '无法将字段解析为JSON',
+ cannotParseValueError: '无法将值解析为JSON',
+ empty: '清空',
+ expandAll: '展开所有字段',
+ expandTitle: '点击 展开/收缩 该字段(Ctrl+E). \n' +
+ 'Ctrl+Click 展开/收缩 包含所有子节点.',
+ insert: '插入',
+ insertTitle: '在此字段前插入类型为“auto”的新字段 (Ctrl+Ins)',
+ insertSub: '选择要插入的字段类型',
+ object: '对象',
+ ok: 'Ok',
+ redo: '重做 (Ctrl+Shift+Z)',
+ removeText: '移除',
+ removeTitle: '移除选中字段 (Ctrl+Del)',
+ removeField: '移除该字段 (Ctrl+Del)',
+ selectNode: '选择一个节点...',
+ showAll: '展示全部',
+ showMore: '展示更多',
+ showMoreStatus: '显示${totalChilds}的${visibleChilds}项目.',
+ sort: '排序',
+ sortTitle: '排序${type}的子节点',
+ sortTitleShort: '内容排序',
+ sortFieldLabel: '字段:',
+ sortDirectionLabel: '方向:',
+ sortFieldTitle: '选择用于对数组或对象排序的嵌套字段',
+ sortAscending: '升序排序',
+ sortAscendingTitle: '按照该字段升序排序',
+ sortDescending: '降序排序',
+ sortDescendingTitle: '按照该字段降序排序',
+ string: '字符串',
+ transform: '变换',
+ transformTitle: '筛选,排序,或者转换${type}的子节点',
+ transformTitleShort: '筛选,排序,或者转换内容',
+ extract: '提取',
+ extractTitle: '提取这个 ${type}',
+ transformQueryTitle: '输入JMESPath查询',
+ transformWizardLabel: '向导',
+ transformWizardFilter: '筛选',
+ transformWizardSortBy: '排序',
+ transformWizardSelectFields: '选择字段',
+ transformQueryLabel: '查询',
+ transformPreviewLabel: '预览',
+ type: '类型',
+ typeTitle: '更改字段类型',
+ openUrl: 'Ctrl+Click 或者 Ctrl+Enter 在新窗口打开链接',
+ undo: '撤销上次动作 (Ctrl+Z)',
+ validationCannotMove: '无法将字段移入其子节点',
+ autoType: '字段类型 "auto". ' +
+ '字段类型由值自动确定 ' +
+ '可以为 string,number,boolean,或者 null.',
+ objectType: '字段类型 "object". ' +
+ '对象包含一组无序的键/值对.',
+ arrayType: '字段类型 "array". ' +
+ '数组包含值的有序集合.',
+ stringType: '字段类型 "string". ' +
+ '字段类型由值自动确定,' +
+ '但始终作为字符串返回.',
+ modeCodeText: '代码',
+ modeCodeTitle: '切换至代码高亮',
+ modeFormText: '表单',
+ modeFormTitle: '切换至表单编辑',
+ modeTextText: '文本',
+ modeTextTitle: '切换至文本编辑',
+ modeTreeText: '树',
+ modeTreeTitle: '切换至树编辑',
+ modeViewText: '视图',
+ modeViewTitle: '切换至树视图',
+ modePreviewText: '预览',
+ modePreviewTitle: '切换至预览模式',
+ examples: '例子',
+ default: '缺省',
+ },
+ 'pt-BR': {
+ array: 'Lista',
+ auto: 'Automatico',
+ appendText: 'Adicionar',
+ appendTitle: 'Adicionar novo campo com tipo \'auto\' depois deste campo (Ctrl+Shift+Ins)',
+ appendSubmenuTitle: 'Selecione o tipo do campo a ser adicionado',
+ appendTitleAuto: 'Adicionar novo campo com tipo \'auto\' (Ctrl+Shift+Ins)',
+ ascending: 'Ascendente',
+ ascendingTitle: 'Organizar filhor do tipo ${type} em crescente',
+ actionsMenu: 'Clique para abrir o menu de ações (Ctrl+M)',
+ collapseAll: 'Fechar todos campos',
+ descending: 'Descendente',
+ descendingTitle: 'Organizar o filhos do tipo ${type} em decrescente',
+ duplicateKey: 'chave duplicada',
+ drag: 'Arraste para mover este campo (Alt+Shift+Arrows)',
+ duplicateText: 'Duplicar',
+ duplicateTitle: 'Duplicar campos selecionados (Ctrl+D)',
+ duplicateField: 'Duplicar este campo (Ctrl+D)',
+ duplicateFieldError: 'Nome do campo duplicado',
+ cannotParseFieldError: 'Não é possível analisar o campo no JSON',
+ cannotParseValueError: 'Não é possível analisar o valor em JSON',
+ empty: 'vazio',
+ expandAll: 'Expandir todos campos',
+ expandTitle: 'Clique para expandir/encolher este campo (Ctrl+E). \n' +
+ 'Ctrl+Click para expandir/encolher incluindo todos os filhos.',
+ insert: 'Inserir',
+ insertTitle: 'Inserir um novo campo do tipo \'auto\' antes deste campo (Ctrl+Ins)',
+ insertSub: 'Selecionar o tipo de campo a ser inserido',
+ object: 'Objeto',
+ ok: 'Ok',
+ redo: 'Refazer (Ctrl+Shift+Z)',
+ removeText: 'Remover',
+ removeTitle: 'Remover campos selecionados (Ctrl+Del)',
+ removeField: 'Remover este campo (Ctrl+Del)',
+ // TODO: correctly translate
+ selectNode: 'Select a node...',
+ // TODO: correctly translate
+ showAll: 'mostre tudo',
+ // TODO: correctly translate
+ showMore: 'mostre mais',
+ // TODO: correctly translate
+ showMoreStatus: 'exibindo ${visibleChilds} de ${totalChilds} itens.',
+ sort: 'Organizar',
+ sortTitle: 'Organizar os filhos deste ${type}',
+ // TODO: correctly translate
+ sortTitleShort: 'Organizar os filhos',
+ // TODO: correctly translate
+ sortFieldLabel: 'Field:',
+ // TODO: correctly translate
+ sortDirectionLabel: 'Direction:',
+ // TODO: correctly translate
+ sortFieldTitle: 'Select the nested field by which to sort the array or object',
+ // TODO: correctly translate
+ sortAscending: 'Ascending',
+ // TODO: correctly translate
+ sortAscendingTitle: 'Sort the selected field in ascending order',
+ // TODO: correctly translate
+ sortDescending: 'Descending',
+ // TODO: correctly translate
+ sortDescendingTitle: 'Sort the selected field in descending order',
+ string: 'Texto',
+ // TODO: correctly translate
+ transform: 'Transform',
+ // TODO: correctly translate
+ transformTitle: 'Filter, sort, or transform the childs of this ${type}',
+ // TODO: correctly translate
+ transformTitleShort: 'Filter, sort, or transform contents',
+ // TODO: correctly translate
+ transformQueryTitle: 'Enter a JMESPath query',
+ // TODO: correctly translate
+ transformWizardLabel: 'Wizard',
+ // TODO: correctly translate
+ transformWizardFilter: 'Filter',
+ // TODO: correctly translate
+ transformWizardSortBy: 'Sort by',
+ // TODO: correctly translate
+ transformWizardSelectFields: 'Select fields',
+ // TODO: correctly translate
+ transformQueryLabel: 'Query',
+ // TODO: correctly translate
+ transformPreviewLabel: 'Preview',
+ type: 'Tipo',
+ typeTitle: 'Mudar o tipo deste campo',
+ openUrl: 'Ctrl+Click ou Ctrl+Enter para abrir link em nova janela',
+ undo: 'Desfazer último ação (Ctrl+Z)',
+ validationCannotMove: 'Não pode mover um campo como filho dele mesmo',
+ autoType: 'Campo do tipo "auto". ' +
+ 'O tipo do campo é determinao automaticamente a partir do seu valor ' +
+ 'e pode ser texto, número, verdade/falso ou nulo.',
+ objectType: 'Campo do tipo "objeto". ' +
+ 'Um objeto contém uma lista de pares com chave e valor.',
+ arrayType: 'Campo do tipo "lista". ' +
+ 'Uma lista contem uma coleção de valores ordenados.',
+ stringType: 'Campo do tipo "string". ' +
+ 'Campo do tipo nao é determinado através do seu valor, ' +
+ 'mas sempre retornara um texto.',
+ examples: 'Exemplos',
+ default: 'Revelia',
+ },
+ tr: {
+ array: 'Dizin',
+ auto: 'Otomatik',
+ appendText: 'Ekle',
+ appendTitle: 'Bu alanın altına \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)',
+ appendSubmenuTitle: 'Eklenecek alanın tipini seç',
+ appendTitleAuto: '\'Otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)',
+ ascending: 'Artan',
+ ascendingTitle: '${type}\'ın alt tiplerini artan düzende sırala',
+ actionsMenu: 'Aksiyon menüsünü açmak için tıklayın (Ctrl+M)',
+ collapseAll: 'Tüm alanları kapat',
+ descending: 'Azalan',
+ descendingTitle: '${type}\'ın alt tiplerini azalan düzende sırala',
+ drag: 'Bu alanı taşımak için sürükleyin (Alt+Shift+Arrows)',
+ duplicateKey: 'Var olan anahtar',
+ duplicateText: 'Aşağıya kopyala',
+ duplicateTitle: 'Seçili alanlardan bir daha oluştur (Ctrl+D)',
+ duplicateField: 'Bu alandan bir daha oluştur (Ctrl+D)',
+ duplicateFieldError: 'Duplicate field name',
+ cannotParseFieldError: 'Alan JSON\'a ayrıştırılamıyor',
+ cannotParseValueError: 'JSON\'a değer ayrıştırılamıyor',
+ empty: 'boş',
+ expandAll: 'Tüm alanları aç',
+ expandTitle: 'Bu alanı açmak/kapatmak için tıkla (Ctrl+E). \n' +
+ 'Alt alanlarda dahil tüm alanları açmak için Ctrl+Click ',
+ insert: 'Ekle',
+ insertTitle: 'Bu alanın üstüne \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Ins)',
+ insertSub: 'Araya eklenecek alanın tipini seç',
+ object: 'Nesne',
+ ok: 'Tamam',
+ redo: 'Yeniden yap (Ctrl+Shift+Z)',
+ removeText: 'Kaldır',
+ removeTitle: 'Seçilen alanları kaldır (Ctrl+Del)',
+ removeField: 'Bu alanı kaldır (Ctrl+Del)',
+ selectNode: 'Bir nesne seç...',
+ showAll: 'tümünü göster',
+ showMore: 'daha fazla göster',
+ showMoreStatus: '${totalChilds} alanın ${visibleChilds} alt alanları gösteriliyor',
+ sort: 'Sırala',
+ sortTitle: '${type}\'ın alt alanlarını sırala',
+ sortTitleShort: 'İçerikleri sırala',
+ sortFieldLabel: 'Alan:',
+ sortDirectionLabel: 'Yön:',
+ sortFieldTitle: 'Diziyi veya nesneyi sıralamak için iç içe geçmiş alanı seçin',
+ sortAscending: 'Artan',
+ sortAscendingTitle: 'Seçili alanı artan düzende sırala',
+ sortDescending: 'Azalan',
+ sortDescendingTitle: 'Seçili alanı azalan düzende sırala',
+ string: 'Karakter Dizisi',
+ transform: 'Dönüştür',
+ transformTitle: '${type}\'ın alt alanlarını filtrele, sırala veya dönüştür',
+ transformTitleShort: 'İçerikleri filterele, sırala veya dönüştür',
+ transformQueryTitle: 'JMESPath sorgusu gir',
+ transformWizardLabel: 'Sihirbaz',
+ transformWizardFilter: 'Filtre',
+ transformWizardSortBy: 'Sırala',
+ transformWizardSelectFields: 'Alanları seç',
+ transformQueryLabel: 'Sorgu',
+ transformPreviewLabel: 'Önizleme',
+ type: 'Tip',
+ typeTitle: 'Bu alanın tipini değiştir',
+ openUrl: 'URL\'i yeni bir pencerede açmak için Ctrl+Click veya Ctrl+Enter',
+ undo: 'Son değişikliği geri al (Ctrl+Z)',
+ validationCannotMove: 'Alt alan olarak taşınamıyor',
+ autoType: 'Alan tipi "otomatik". ' +
+ 'Alan türü otomatik olarak değerden belirlenir' +
+ 've bir dize, sayı, boolean veya null olabilir.',
+ objectType: 'Alan tipi "nesne". ' +
+ 'Bir nesne, sıralanmamış bir anahtar / değer çifti kümesi içerir.',
+ arrayType: 'Alan tipi "dizi". ' +
+ 'Bir dizi, düzenli değerler koleksiyonu içerir.',
+ stringType: 'Alan tipi "karakter dizisi". ' +
+ 'Alan türü değerden belirlenmez,' +
+ 'ancak her zaman karakter dizisi olarak döndürülür.',
+ modeCodeText: 'Kod',
+ modeCodeTitle: 'Kod vurgulayıcıya geç',
+ modeFormText: 'Form',
+ modeFormTitle: 'Form düzenleyiciye geç',
+ modeTextText: 'Metin',
+ modeTextTitle: 'Düz metin düzenleyiciye geç',
+ modeTreeText: 'Ağaç',
+ modeTreeTitle: 'Ağaç düzenleyiciye geç',
+ modeViewText: 'Görünüm',
+ modeViewTitle: 'Ağaç görünümüne geç',
+ examples: 'Örnekler',
+ default: 'Varsayılan',
+ }
+};
+
+var _defaultLang = 'en';
+var _lang;
+var userLang = typeof navigator !== 'undefined' ?
+ navigator.language || navigator.userLanguage :
+ undefined;
+_lang = _locales.find(function (l) {
+ return l === userLang;
+});
+if (!_lang) {
+ _lang = _defaultLang;
+}
+
+module.exports = {
+ // supported locales
+ _locales: _locales,
+ _defs: _defs,
+ _lang: _lang,
+ setLanguage: function (lang) {
+ if (!lang) {
+ return;
+ }
+ var langFound = _locales.find(function (l) {
+ return l === lang;
+ });
+ if (langFound) {
+ _lang = langFound;
+ } else {
+ console.error('Language not found');
+ }
+ },
+ setLanguages: function (languages) {
+ if (!languages) {
+ return;
+ }
+ for (var key in languages) {
+ var langFound = _locales.find(function (l) {
+ return l === key;
+ });
+ if (!langFound) {
+ _locales.push(key);
+ }
+ _defs[key] = Object.assign({}, _defs[_defaultLang], _defs[key], languages[key]);
+ }
+ },
+ translate: function (key, data, lang) {
+ if (!lang) {
+ lang = _lang;
+ }
+ var text = _defs[lang][key];
+ if (data) {
+ for (key in data) {
+ text = text.replace('${' + key + '}', data[key]);
+ }
+ }
+ return text || key;
+ }
};
/***/ }),
/* 2 */
/***/ (function(module, exports) {
-
-exports.DEFAULT_MODAL_ANCHOR = document.body;
-exports.SIZE_LARGE = 10 * 1024 * 1024; // 10 MB
-
-exports.MAX_PREVIEW_CHARACTERS = 20000;
-
-exports.PREVIEW_HISTORY_LIMIT = 2 * 1024 * 1024 * 1024; // 2 GB
+
+exports.DEFAULT_MODAL_ANCHOR = document.body;
+exports.SIZE_LARGE = 10 * 1024 * 1024; // 10 MB
+
+exports.MAX_PREVIEW_CHARACTERS = 20000;
+
+exports.PREVIEW_HISTORY_LIMIT = 2 * 1024 * 1024 * 1024; // 2 GB
/***/ }),
@@ -2304,444 +2304,444 @@ function unescapeJsonPointer(str) {
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-
-
-var createAbsoluteAnchor = __webpack_require__(25).createAbsoluteAnchor;
-var util = __webpack_require__(0);
-var translate = __webpack_require__(1).translate;
-
-/**
- * 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
- */
-function ContextMenu (items, options) {
- this.dom = {};
-
- var me = this;
- var dom = this.dom;
- this.anchor = undefined;
- this.items = items;
- this.eventListeners = {};
- this.selection = undefined; // holds the selection before the menu was opened
- this.onClose = options ? options.close : undefined;
-
- // create root element
- var root = document.createElement('div');
- root.className = 'jsoneditor-contextmenu-root';
- dom.root = root;
-
- // create a container element
- var menu = document.createElement('div');
- menu.className = 'jsoneditor-contextmenu';
- dom.menu = menu;
- root.appendChild(menu);
-
- // create a list to hold the menu items
- var list = document.createElement('ul');
- list.className = 'jsoneditor-menu';
- menu.appendChild(list);
- dom.list = list;
- dom.items = []; // list with all buttons
-
- // create a (non-visible) button to set the focus to the menu
- var focusButton = document.createElement('button');
- focusButton.type = 'button';
- dom.focusButton = focusButton;
- var li = document.createElement('li');
- li.style.overflow = 'hidden';
- li.style.height = '0';
- li.appendChild(focusButton);
- list.appendChild(li);
-
- function createMenuItems (list, domItems, items) {
- items.forEach(function (item) {
- if (item.type == 'separator') {
- // create a separator
- var separator = document.createElement('div');
- separator.className = 'jsoneditor-separator';
- li = document.createElement('li');
- li.appendChild(separator);
- list.appendChild(li);
- }
- else {
- var domItem = {};
-
- // 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.type = 'button';
- button.className = item.className;
- domItem.button = button;
- if (item.title) {
- button.title = item.title;
- }
- if (item.click) {
- button.onclick = function (event) {
- event.preventDefault();
- 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 = 'jsoneditor-icon';
- button.appendChild(divIcon);
- var divText = document.createElement('div');
- divText.className = 'jsoneditor-text' +
- (item.click ? '' : ' jsoneditor-right-margin');
- divText.appendChild(document.createTextNode(item.text));
- button.appendChild(divText);
-
- var buttonSubmenu;
- if (item.click) {
- // submenu and a button with a click handler
- button.className += ' jsoneditor-default';
-
- var buttonExpand = document.createElement('button');
- buttonExpand.type = 'button';
- domItem.buttonExpand = buttonExpand;
- buttonExpand.className = 'jsoneditor-expand';
- buttonExpand.innerHTML = '';
- 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 = 'jsoneditor-expand';
- button.appendChild(divExpand);
-
- buttonSubmenu = button;
- }
-
- // attach a handler to expand/collapse the submenu
- buttonSubmenu.onclick = function (event) {
- event.preventDefault();
- me._onExpandItem(domItem);
- buttonSubmenu.focus();
- };
-
- // create the submenu
- var domSubItems = [];
- domItem.subItems = domSubItems;
- var ul = document.createElement('ul');
- domItem.ul = ul;
- ul.className = 'jsoneditor-menu';
- ul.style.height = '0';
- li.appendChild(ul);
- createMenuItems(ul, domSubItems, item.submenu);
- }
- else {
- // no submenu, just a button with clickhandler
- button.innerHTML = '' +
- '' + translate(item.text) + '
';
- }
-
- domItems.push(domItem);
- }
- });
- }
- createMenuItems(list, this.dom.items, 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);
- });
-}
-
-/**
- * Get the currently visible buttons
- * @return {Array.} buttons
- * @private
- */
-ContextMenu.prototype._getVisibleButtons = function () {
- var buttons = [];
- var me = this;
- this.dom.items.forEach(function (item) {
- buttons.push(item.button);
- if (item.buttonExpand) {
- buttons.push(item.buttonExpand);
- }
- if (item.subItems && item == me.expandedItem) {
- item.subItems.forEach(function (subItem) {
- buttons.push(subItem.button);
- if (subItem.buttonExpand) {
- buttons.push(subItem.buttonExpand);
- }
- // TODO: change to fully recursive method
- });
- }
- });
-
- return buttons;
-};
-
-// currently displayed context menu, a singleton. We may only have one visible context menu
-ContextMenu.visibleMenu = undefined;
-
-/**
- * Attach the menu to an anchor
- * @param {HTMLElement} anchor Anchor where the menu will be attached as sibling.
- * @param {HTMLElement} frame The root of the JSONEditor window
- * @param {Boolean=} ignoreParent ignore anchor parent in regard to the calculation of the position, needed when the parent position is absolute
- */
-ContextMenu.prototype.show = function (anchor, frame, ignoreParent) {
- this.hide();
-
- // determine whether to display the menu below or above the anchor
- var showBelow = true;
- var parent = anchor.parentNode;
- var anchorRect = anchor.getBoundingClientRect();
- var parentRect = parent.getBoundingClientRect();
- var frameRect = frame.getBoundingClientRect();
-
- var me = this;
- this.dom.absoluteAnchor = createAbsoluteAnchor(anchor, frame, function () {
- me.hide()
- });
-
- if (anchorRect.bottom + this.maxHeight < frameRect.bottom) {
- // fits below -> show below
- }
- else if (anchorRect.top - this.maxHeight > frameRect.top) {
- // fits above -> show above
- showBelow = false;
- }
- else {
- // doesn't fit above nor below -> show below
- }
-
- var topGap = ignoreParent ? 0 : (anchorRect.top - parentRect.top);
-
- // position the menu
- if (showBelow) {
- // display the menu below the anchor
- var anchorHeight = anchor.offsetHeight;
- this.dom.menu.style.left = '0';
- this.dom.menu.style.top = topGap + anchorHeight + 'px';
- this.dom.menu.style.bottom = '';
- }
- else {
- // display the menu above the anchor
- this.dom.menu.style.left = '0';
- this.dom.menu.style.top = '';
- this.dom.menu.style.bottom = '0px';
- }
-
- // attach the menu to the temporary, absolute anchor
- // parent.insertBefore(this.dom.root, anchor);
- this.dom.absoluteAnchor.appendChild(this.dom.root);
-
- // move focus to the first button in the context menu
- this.selection = util.getSelection();
- this.anchor = anchor;
- setTimeout(function () {
- me.dom.focusButton.focus();
- }, 0);
-
- if (ContextMenu.visibleMenu) {
- ContextMenu.visibleMenu.hide();
- }
- ContextMenu.visibleMenu = this;
-};
-
-/**
- * Hide the context menu if visible
- */
-ContextMenu.prototype.hide = function () {
- // remove temporary absolutely positioned anchor
- if (this.dom.absoluteAnchor) {
- this.dom.absoluteAnchor.destroy();
- delete this.dom.absoluteAnchor;
- }
-
- // remove the menu from the DOM
- if (this.dom.root.parentNode) {
- this.dom.root.parentNode.removeChild(this.dom.root);
- if (this.onClose) {
- this.onClose();
- }
- }
-
- if (ContextMenu.visibleMenu == this) {
- ContextMenu.visibleMenu = undefined;
- }
-};
-
-/**
- * Expand a submenu
- * Any currently expanded submenu will be hided.
- * @param {Object} domItem
- * @private
- */
-ContextMenu.prototype._onExpandItem = function (domItem) {
- var me = this;
- var alreadyVisible = (domItem == this.expandedItem);
-
- // hide the currently visible submenu
- var expandedItem = this.expandedItem;
- if (expandedItem) {
- //var ul = expandedItem.ul;
- expandedItem.ul.style.height = '0';
- expandedItem.ul.style.padding = '';
- setTimeout(function () {
- if (me.expandedItem != expandedItem) {
- expandedItem.ul.style.display = '';
- util.removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected');
- }
- }, 300); // timeout duration must match the css transition duration
- this.expandedItem = undefined;
- }
-
- if (!alreadyVisible) {
- var ul = domItem.ul;
- ul.style.display = 'block';
- var height = ul.clientHeight; // force a reflow in Firefox
- setTimeout(function () {
- if (me.expandedItem == domItem) {
- var childsHeight = 0;
- for (var i = 0; i < ul.childNodes.length; i++) {
- childsHeight += ul.childNodes[i].clientHeight;
- }
- ul.style.height = childsHeight + 'px';
- ul.style.padding = '5px 10px';
- }
- }, 0);
- util.addClassName(ul.parentNode, 'jsoneditor-selected');
- this.expandedItem = domItem;
- }
-};
-
-/**
- * Handle onkeydown event
- * @param {Event} event
- * @private
- */
-ContextMenu.prototype._onKeyDown = function (event) {
- var target = event.target;
- var keynum = event.which;
- var handled = false;
- var buttons, targetIndex, prevButton, nextButton;
-
- if (keynum == 27) { // ESC
- // hide the menu on ESC key
-
- // restore previous selection and focus
- if (this.selection) {
- util.setSelection(this.selection);
- }
- if (this.anchor) {
- this.anchor.focus();
- }
-
- this.hide();
-
- handled = true;
- }
- else if (keynum == 9) { // Tab
- if (!event.shiftKey) { // Tab
- buttons = this._getVisibleButtons();
- targetIndex = buttons.indexOf(target);
- if (targetIndex == buttons.length - 1) {
- // move to first button
- buttons[0].focus();
- handled = true;
- }
- }
- else { // Shift+Tab
- buttons = this._getVisibleButtons();
- targetIndex = buttons.indexOf(target);
- if (targetIndex == 0) {
- // move to last button
- buttons[buttons.length - 1].focus();
- handled = true;
- }
- }
- }
- else if (keynum == 37) { // Arrow Left
- if (target.className == 'jsoneditor-expand') {
- buttons = this._getVisibleButtons();
- targetIndex = buttons.indexOf(target);
- prevButton = buttons[targetIndex - 1];
- if (prevButton) {
- prevButton.focus();
- }
- }
- handled = true;
- }
- else if (keynum == 38) { // Arrow Up
- buttons = this._getVisibleButtons();
- targetIndex = buttons.indexOf(target);
- prevButton = buttons[targetIndex - 1];
- if (prevButton && prevButton.className == 'jsoneditor-expand') {
- // skip expand button
- prevButton = buttons[targetIndex - 2];
- }
- if (!prevButton) {
- // move to last button
- prevButton = buttons[buttons.length - 1];
- }
- if (prevButton) {
- prevButton.focus();
- }
- handled = true;
- }
- else if (keynum == 39) { // Arrow Right
- buttons = this._getVisibleButtons();
- targetIndex = buttons.indexOf(target);
- nextButton = buttons[targetIndex + 1];
- if (nextButton && nextButton.className == 'jsoneditor-expand') {
- nextButton.focus();
- }
- handled = true;
- }
- else if (keynum == 40) { // Arrow Down
- buttons = this._getVisibleButtons();
- targetIndex = buttons.indexOf(target);
- nextButton = buttons[targetIndex + 1];
- if (nextButton && nextButton.className == 'jsoneditor-expand') {
- // skip expand button
- nextButton = buttons[targetIndex + 2];
- }
- if (!nextButton) {
- // move to first button
- nextButton = buttons[0];
- }
- if (nextButton) {
- nextButton.focus();
- handled = true;
- }
- handled = true;
- }
- // TODO: arrow left and right
-
- if (handled) {
- event.stopPropagation();
- event.preventDefault();
- }
-};
-
-module.exports = ContextMenu;
+
+
+var createAbsoluteAnchor = __webpack_require__(25).createAbsoluteAnchor;
+var util = __webpack_require__(0);
+var translate = __webpack_require__(1).translate;
+
+/**
+ * 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
+ */
+function ContextMenu (items, options) {
+ this.dom = {};
+
+ var me = this;
+ var dom = this.dom;
+ this.anchor = undefined;
+ this.items = items;
+ this.eventListeners = {};
+ this.selection = undefined; // holds the selection before the menu was opened
+ this.onClose = options ? options.close : undefined;
+
+ // create root element
+ var root = document.createElement('div');
+ root.className = 'jsoneditor-contextmenu-root';
+ dom.root = root;
+
+ // create a container element
+ var menu = document.createElement('div');
+ menu.className = 'jsoneditor-contextmenu';
+ dom.menu = menu;
+ root.appendChild(menu);
+
+ // create a list to hold the menu items
+ var list = document.createElement('ul');
+ list.className = 'jsoneditor-menu';
+ menu.appendChild(list);
+ dom.list = list;
+ dom.items = []; // list with all buttons
+
+ // create a (non-visible) button to set the focus to the menu
+ var focusButton = document.createElement('button');
+ focusButton.type = 'button';
+ dom.focusButton = focusButton;
+ var li = document.createElement('li');
+ li.style.overflow = 'hidden';
+ li.style.height = '0';
+ li.appendChild(focusButton);
+ list.appendChild(li);
+
+ function createMenuItems (list, domItems, items) {
+ items.forEach(function (item) {
+ if (item.type == 'separator') {
+ // create a separator
+ var separator = document.createElement('div');
+ separator.className = 'jsoneditor-separator';
+ li = document.createElement('li');
+ li.appendChild(separator);
+ list.appendChild(li);
+ }
+ else {
+ var domItem = {};
+
+ // 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.type = 'button';
+ button.className = item.className;
+ domItem.button = button;
+ if (item.title) {
+ button.title = item.title;
+ }
+ if (item.click) {
+ button.onclick = function (event) {
+ event.preventDefault();
+ 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 = 'jsoneditor-icon';
+ button.appendChild(divIcon);
+ var divText = document.createElement('div');
+ divText.className = 'jsoneditor-text' +
+ (item.click ? '' : ' jsoneditor-right-margin');
+ divText.appendChild(document.createTextNode(item.text));
+ button.appendChild(divText);
+
+ var buttonSubmenu;
+ if (item.click) {
+ // submenu and a button with a click handler
+ button.className += ' jsoneditor-default';
+
+ var buttonExpand = document.createElement('button');
+ buttonExpand.type = 'button';
+ domItem.buttonExpand = buttonExpand;
+ buttonExpand.className = 'jsoneditor-expand';
+ buttonExpand.innerHTML = '';
+ 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 = 'jsoneditor-expand';
+ button.appendChild(divExpand);
+
+ buttonSubmenu = button;
+ }
+
+ // attach a handler to expand/collapse the submenu
+ buttonSubmenu.onclick = function (event) {
+ event.preventDefault();
+ me._onExpandItem(domItem);
+ buttonSubmenu.focus();
+ };
+
+ // create the submenu
+ var domSubItems = [];
+ domItem.subItems = domSubItems;
+ var ul = document.createElement('ul');
+ domItem.ul = ul;
+ ul.className = 'jsoneditor-menu';
+ ul.style.height = '0';
+ li.appendChild(ul);
+ createMenuItems(ul, domSubItems, item.submenu);
+ }
+ else {
+ // no submenu, just a button with clickhandler
+ button.innerHTML = '' +
+ '' + translate(item.text) + '
';
+ }
+
+ domItems.push(domItem);
+ }
+ });
+ }
+ createMenuItems(list, this.dom.items, 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);
+ });
+}
+
+/**
+ * Get the currently visible buttons
+ * @return {Array.} buttons
+ * @private
+ */
+ContextMenu.prototype._getVisibleButtons = function () {
+ var buttons = [];
+ var me = this;
+ this.dom.items.forEach(function (item) {
+ buttons.push(item.button);
+ if (item.buttonExpand) {
+ buttons.push(item.buttonExpand);
+ }
+ if (item.subItems && item == me.expandedItem) {
+ item.subItems.forEach(function (subItem) {
+ buttons.push(subItem.button);
+ if (subItem.buttonExpand) {
+ buttons.push(subItem.buttonExpand);
+ }
+ // TODO: change to fully recursive method
+ });
+ }
+ });
+
+ return buttons;
+};
+
+// currently displayed context menu, a singleton. We may only have one visible context menu
+ContextMenu.visibleMenu = undefined;
+
+/**
+ * Attach the menu to an anchor
+ * @param {HTMLElement} anchor Anchor where the menu will be attached as sibling.
+ * @param {HTMLElement} frame The root of the JSONEditor window
+ * @param {Boolean=} ignoreParent ignore anchor parent in regard to the calculation of the position, needed when the parent position is absolute
+ */
+ContextMenu.prototype.show = function (anchor, frame, ignoreParent) {
+ this.hide();
+
+ // determine whether to display the menu below or above the anchor
+ var showBelow = true;
+ var parent = anchor.parentNode;
+ var anchorRect = anchor.getBoundingClientRect();
+ var parentRect = parent.getBoundingClientRect();
+ var frameRect = frame.getBoundingClientRect();
+
+ var me = this;
+ this.dom.absoluteAnchor = createAbsoluteAnchor(anchor, frame, function () {
+ me.hide()
+ });
+
+ if (anchorRect.bottom + this.maxHeight < frameRect.bottom) {
+ // fits below -> show below
+ }
+ else if (anchorRect.top - this.maxHeight > frameRect.top) {
+ // fits above -> show above
+ showBelow = false;
+ }
+ else {
+ // doesn't fit above nor below -> show below
+ }
+
+ var topGap = ignoreParent ? 0 : (anchorRect.top - parentRect.top);
+
+ // position the menu
+ if (showBelow) {
+ // display the menu below the anchor
+ var anchorHeight = anchor.offsetHeight;
+ this.dom.menu.style.left = '0';
+ this.dom.menu.style.top = topGap + anchorHeight + 'px';
+ this.dom.menu.style.bottom = '';
+ }
+ else {
+ // display the menu above the anchor
+ this.dom.menu.style.left = '0';
+ this.dom.menu.style.top = '';
+ this.dom.menu.style.bottom = '0px';
+ }
+
+ // attach the menu to the temporary, absolute anchor
+ // parent.insertBefore(this.dom.root, anchor);
+ this.dom.absoluteAnchor.appendChild(this.dom.root);
+
+ // move focus to the first button in the context menu
+ this.selection = util.getSelection();
+ this.anchor = anchor;
+ setTimeout(function () {
+ me.dom.focusButton.focus();
+ }, 0);
+
+ if (ContextMenu.visibleMenu) {
+ ContextMenu.visibleMenu.hide();
+ }
+ ContextMenu.visibleMenu = this;
+};
+
+/**
+ * Hide the context menu if visible
+ */
+ContextMenu.prototype.hide = function () {
+ // remove temporary absolutely positioned anchor
+ if (this.dom.absoluteAnchor) {
+ this.dom.absoluteAnchor.destroy();
+ delete this.dom.absoluteAnchor;
+ }
+
+ // remove the menu from the DOM
+ if (this.dom.root.parentNode) {
+ this.dom.root.parentNode.removeChild(this.dom.root);
+ if (this.onClose) {
+ this.onClose();
+ }
+ }
+
+ if (ContextMenu.visibleMenu == this) {
+ ContextMenu.visibleMenu = undefined;
+ }
+};
+
+/**
+ * Expand a submenu
+ * Any currently expanded submenu will be hided.
+ * @param {Object} domItem
+ * @private
+ */
+ContextMenu.prototype._onExpandItem = function (domItem) {
+ var me = this;
+ var alreadyVisible = (domItem == this.expandedItem);
+
+ // hide the currently visible submenu
+ var expandedItem = this.expandedItem;
+ if (expandedItem) {
+ //var ul = expandedItem.ul;
+ expandedItem.ul.style.height = '0';
+ expandedItem.ul.style.padding = '';
+ setTimeout(function () {
+ if (me.expandedItem != expandedItem) {
+ expandedItem.ul.style.display = '';
+ util.removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected');
+ }
+ }, 300); // timeout duration must match the css transition duration
+ this.expandedItem = undefined;
+ }
+
+ if (!alreadyVisible) {
+ var ul = domItem.ul;
+ ul.style.display = 'block';
+ var height = ul.clientHeight; // force a reflow in Firefox
+ setTimeout(function () {
+ if (me.expandedItem == domItem) {
+ var childsHeight = 0;
+ for (var i = 0; i < ul.childNodes.length; i++) {
+ childsHeight += ul.childNodes[i].clientHeight;
+ }
+ ul.style.height = childsHeight + 'px';
+ ul.style.padding = '5px 10px';
+ }
+ }, 0);
+ util.addClassName(ul.parentNode, 'jsoneditor-selected');
+ this.expandedItem = domItem;
+ }
+};
+
+/**
+ * Handle onkeydown event
+ * @param {Event} event
+ * @private
+ */
+ContextMenu.prototype._onKeyDown = function (event) {
+ var target = event.target;
+ var keynum = event.which;
+ var handled = false;
+ var buttons, targetIndex, prevButton, nextButton;
+
+ if (keynum == 27) { // ESC
+ // hide the menu on ESC key
+
+ // restore previous selection and focus
+ if (this.selection) {
+ util.setSelection(this.selection);
+ }
+ if (this.anchor) {
+ this.anchor.focus();
+ }
+
+ this.hide();
+
+ handled = true;
+ }
+ else if (keynum == 9) { // Tab
+ if (!event.shiftKey) { // Tab
+ buttons = this._getVisibleButtons();
+ targetIndex = buttons.indexOf(target);
+ if (targetIndex == buttons.length - 1) {
+ // move to first button
+ buttons[0].focus();
+ handled = true;
+ }
+ }
+ else { // Shift+Tab
+ buttons = this._getVisibleButtons();
+ targetIndex = buttons.indexOf(target);
+ if (targetIndex == 0) {
+ // move to last button
+ buttons[buttons.length - 1].focus();
+ handled = true;
+ }
+ }
+ }
+ else if (keynum == 37) { // Arrow Left
+ if (target.className == 'jsoneditor-expand') {
+ buttons = this._getVisibleButtons();
+ targetIndex = buttons.indexOf(target);
+ prevButton = buttons[targetIndex - 1];
+ if (prevButton) {
+ prevButton.focus();
+ }
+ }
+ handled = true;
+ }
+ else if (keynum == 38) { // Arrow Up
+ buttons = this._getVisibleButtons();
+ targetIndex = buttons.indexOf(target);
+ prevButton = buttons[targetIndex - 1];
+ if (prevButton && prevButton.className == 'jsoneditor-expand') {
+ // skip expand button
+ prevButton = buttons[targetIndex - 2];
+ }
+ if (!prevButton) {
+ // move to last button
+ prevButton = buttons[buttons.length - 1];
+ }
+ if (prevButton) {
+ prevButton.focus();
+ }
+ handled = true;
+ }
+ else if (keynum == 39) { // Arrow Right
+ buttons = this._getVisibleButtons();
+ targetIndex = buttons.indexOf(target);
+ nextButton = buttons[targetIndex + 1];
+ if (nextButton && nextButton.className == 'jsoneditor-expand') {
+ nextButton.focus();
+ }
+ handled = true;
+ }
+ else if (keynum == 40) { // Arrow Down
+ buttons = this._getVisibleButtons();
+ targetIndex = buttons.indexOf(target);
+ nextButton = buttons[targetIndex + 1];
+ if (nextButton && nextButton.className == 'jsoneditor-expand') {
+ // skip expand button
+ nextButton = buttons[targetIndex + 2];
+ }
+ if (!nextButton) {
+ // move to first button
+ nextButton = buttons[0];
+ }
+ if (nextButton) {
+ nextButton.focus();
+ handled = true;
+ }
+ handled = true;
+ }
+ // TODO: arrow left and right
+
+ if (handled) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+};
+
+module.exports = ContextMenu;
/***/ }),
@@ -4801,437 +4801,445 @@ function errorSubclass(Subclass) {
/* 9 */
/***/ (function(module, exports, __webpack_require__) {
-var picoModal = __webpack_require__(26);
-var translate = __webpack_require__(1).translate;
-var util = __webpack_require__(0);
-
-/**
- * Show advanced sorting modal
- * @param {HTMLElement} container The container where to center
- * the modal and create an overlay
- * @param {JSON} json The JSON data to be sorted.
- * @param {function} onSort Callback function, invoked with
- * an object containing the selected
- * path and direction
- * @param {Object} options
- * Available options:
- * - {string} path The selected path
- * - {'asc' | 'desc'} direction The selected direction
- */
-function showSortModal (container, json, onSort, options) {
- var paths = Array.isArray(json)
- ? util.getChildPaths(json)
- : [''];
- var selectedPath = options && options.path && util.contains(paths, options.path)
- ? options.path
- : paths[0]
- var selectedDirection = options && options.direction || 'asc'
-
- var content = '';
-
- picoModal({
- parent: container,
- content: content,
- overlayClass: 'jsoneditor-modal-overlay',
- modalClass: 'jsoneditor-modal jsoneditor-modal-sort'
- })
- .afterCreate(function (modal) {
- var form = modal.modalElem().querySelector('form');
- var ok = modal.modalElem().querySelector('#ok');
- var field = modal.modalElem().querySelector('#field');
- var direction = modal.modalElem().querySelector('#direction');
-
- function preprocessPath(path) {
- return (path === '')
- ? '@'
- : (path[0] === '.')
- ? path.slice(1)
- : path;
- }
-
- paths.forEach(function (path) {
- var option = document.createElement('option');
- option.text = preprocessPath(path);
- option.value = path;
- field.appendChild(option);
- });
-
- function setDirection(value) {
- direction.value = value;
- direction.className = 'jsoneditor-button-group jsoneditor-button-group-value-' + direction.value;
- }
-
- field.value = selectedPath || paths[0];
- setDirection(selectedDirection || 'asc');
-
- direction.onclick = function (event) {
- setDirection(event.target.getAttribute('data-value'));
- };
-
- ok.onclick = function (event) {
- event.preventDefault();
- event.stopPropagation();
-
- modal.close();
-
- onSort({
- path: field.value,
- direction: direction.value
- })
- };
-
- if (form) { // form is not available when JSONEditor is created inside a form
- form.onsubmit = ok.onclick;
- }
- })
- .afterClose(function (modal) {
- modal.destroy();
- })
- .show();
-}
-
-module.exports = showSortModal;
+var picoModal = __webpack_require__(26);
+var translate = __webpack_require__(1).translate;
+var util = __webpack_require__(0);
+
+/**
+ * Show advanced sorting modal
+ * @param {HTMLElement} container The container where to center
+ * the modal and create an overlay
+ * @param {JSON} json The JSON data to be sorted.
+ * @param {function} onSort Callback function, invoked with
+ * an object containing the selected
+ * path and direction
+ * @param {Object} options
+ * Available options:
+ * - {string} path The selected path
+ * - {'asc' | 'desc'} direction The selected direction
+ */
+function showSortModal (container, json, onSort, options) {
+ var paths = Array.isArray(json)
+ ? util.getChildPaths(json)
+ : [''];
+ var selectedPath = options && options.path && util.contains(paths, options.path)
+ ? options.path
+ : paths[0]
+ var selectedDirection = options && options.direction || 'asc'
+
+ var content = '';
+
+ picoModal({
+ parent: container,
+ content: content,
+ overlayClass: 'jsoneditor-modal-overlay',
+ overlayStyles: {
+ backgroundColor: "rgb(1,1,1)",
+ opacity: 0.3
+ },
+ modalClass: 'jsoneditor-modal jsoneditor-modal-sort'
+ })
+ .afterCreate(function (modal) {
+ var form = modal.modalElem().querySelector('form');
+ var ok = modal.modalElem().querySelector('#ok');
+ var field = modal.modalElem().querySelector('#field');
+ var direction = modal.modalElem().querySelector('#direction');
+
+ function preprocessPath(path) {
+ return (path === '')
+ ? '@'
+ : (path[0] === '.')
+ ? path.slice(1)
+ : path;
+ }
+
+ paths.forEach(function (path) {
+ var option = document.createElement('option');
+ option.text = preprocessPath(path);
+ option.value = path;
+ field.appendChild(option);
+ });
+
+ function setDirection(value) {
+ direction.value = value;
+ direction.className = 'jsoneditor-button-group jsoneditor-button-group-value-' + direction.value;
+ }
+
+ field.value = selectedPath || paths[0];
+ setDirection(selectedDirection || 'asc');
+
+ direction.onclick = function (event) {
+ setDirection(event.target.getAttribute('data-value'));
+ };
+
+ ok.onclick = function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ modal.close();
+
+ onSort({
+ path: field.value,
+ direction: direction.value
+ })
+ };
+
+ if (form) { // form is not available when JSONEditor is created inside a form
+ form.onsubmit = ok.onclick;
+ }
+ })
+ .afterClose(function (modal) {
+ modal.destroy();
+ })
+ .show();
+}
+
+module.exports = showSortModal;
/***/ }),
/* 10 */
/***/ (function(module, exports, __webpack_require__) {
-var jmespath = __webpack_require__(5);
-var picoModal = __webpack_require__(26);
-var Selectr = __webpack_require__(79);
-var translate = __webpack_require__(1).translate;
-var stringifyPartial = __webpack_require__(80).stringifyPartial;
-var util = __webpack_require__(0);
-var MAX_PREVIEW_CHARACTERS = __webpack_require__(2).MAX_PREVIEW_CHARACTERS
-var debounce = util.debounce;
-
-/**
- * Show advanced filter and transform modal using JMESPath
- * @param {HTMLElement} container The container where to center
- * the modal and create an overlay
- * @param {JSON} json The json data to be transformed
- * @param {function} onTransform Callback invoked with the created
- * query as callback
- */
-function showTransformModal (container, json, onTransform) {
- var value = json;
-
- var content = '