diff --git a/src/jsoneditor/components/JSONNode.js b/src/jsoneditor/components/JSONNode.js
index cd2d2e5..61a65c5 100644
--- a/src/jsoneditor/components/JSONNode.js
+++ b/src/jsoneditor/components/JSONNode.js
@@ -9,7 +9,8 @@ import { stringConvert, valueType, isUrl } from '../utils/typeUtils'
import {
compileJSONPointer,
META,
- SELECTED, SELECTED_START, SELECTED_END, SELECTED_AFTER, SELECTED_BEFORE, SELECTED_FIRST, SELECTED_LAST
+ SELECTED, SELECTED_START, SELECTED_END, SELECTED_AFTER, SELECTED_BEFORE,
+ SELECTED_FIRST, SELECTED_LAST
} from '../eson'
const MENU_ITEMS_OBJECT = [
@@ -108,9 +109,12 @@ export default class JSONNode extends PureComponent {
? [
this.renderTag(`${props.length} ${props.length === 1 ? 'prop' : 'props'}`,
`Object containing ${props.length} ${props.length === 1 ? 'property' : 'properties'}`),
- this.renderDelimiter('}', 'jsoneditor-delimiter-start'),
+ this.renderDelimiter('}', 'jsoneditor-delimiter-end jsoneditor-delimiter-collapsed'),
+ this.renderInsertAfter()
]
- : null,
+ : [
+ this.renderInsertBefore()
+ ],
this.renderError(meta.error)
])
@@ -129,24 +133,27 @@ export default class JSONNode extends PureComponent {
childs = h('div', {key: 'childs', className: 'jsoneditor-list'}, propsChilds)
}
else {
- childs = h('div', {key: 'childs', className: 'jsoneditor-list'},
+ childs = h('div', {key: 'childs', className: 'jsoneditor-list', 'data-area': 'emptyBefore'},
this.renderAppend('(empty object)')
)
}
}
const floatingMenu = this.renderFloatingMenu(MENU_ITEMS_OBJECT, meta.selected)
- const insertArea = this.renderInsertBeforeArea()
const nodeEnd = meta.expanded
- ? this.renderDelimiter('}', 'jsoneditor-delimiter-end')
+ ? h('div', {key: 'node-end', className: 'jsoneditor-node-end', 'data-area': 'empty'}, [
+ this.renderDelimiter('}', 'jsoneditor-delimiter-end'),
+ this.renderInsertAfter()
+ ])
: null
return h('div', {
'data-path': compileJSONPointer(meta.path),
+ 'data-area': 'empty',
className: this.getContainerClassName(meta.selected, this.state.hover),
// onMouseOver: this.handleMouseOver,
// onMouseLeave: this.handleMouseLeave
- }, [nodeStart, floatingMenu, insertArea, childs, nodeEnd])
+ }, [floatingMenu, nodeStart, childs, nodeEnd])
}
renderJSONArray () {
@@ -158,7 +165,6 @@ export default class JSONNode extends PureComponent {
className: 'jsoneditor-node jsoneditor-array'
}, [
this.renderExpandButton(),
- // this.renderDelimiter('\u2611'),
this.renderProperty(),
this.renderSeparator(),
this.renderDelimiter('[', 'jsoneditor-delimiter-start'),
@@ -166,9 +172,12 @@ export default class JSONNode extends PureComponent {
? [
this.renderTag(`${count} ${count === 1 ? 'item' : 'items'}`,
`Array containing ${count} item${count === 1 ? 'item' : 'items'}`),
- this.renderDelimiter(']', 'jsoneditor-delimiter-start'),
+ this.renderDelimiter(']', 'jsoneditor-delimiter-end jsoneditor-delimiter-collapsed'),
+ this.renderInsertAfter(),
]
- : null,
+ : [
+ this.renderInsertBefore()
+ ],
this.renderError(meta.error)
])
@@ -186,24 +195,27 @@ export default class JSONNode extends PureComponent {
childs = h('div', {key: 'childs', className: 'jsoneditor-list'}, items)
}
else {
- childs = h('div', {key: 'childs', className: 'jsoneditor-list'},
+ childs = h('div', {key: 'childs', className: 'jsoneditor-list', 'data-area': 'emptyBefore'},
this.renderAppend('(empty array)')
)
}
}
const floatingMenu = this.renderFloatingMenu(MENU_ITEMS_ARRAY, meta.selected)
- const insertArea = this.renderInsertBeforeArea()
const nodeEnd = meta.expanded
- ? this.renderDelimiter(']', 'jsoneditor-delimiter-end')
+ ? h('div', {key: 'node-end', className: 'jsoneditor-node-end', 'data-area': 'empty'}, [
+ this.renderDelimiter(']', 'jsoneditor-delimiter-end'),
+ this.renderInsertAfter()
+ ])
: null
return h('div', {
'data-path': compileJSONPointer(meta.path),
+ 'data-area': 'empty',
className: this.getContainerClassName(meta.selected, this.state.hover),
// onMouseOver: this.handleMouseOver,
// onMouseLeave: this.handleMouseLeave
- }, [nodeStart, floatingMenu, insertArea, childs, nodeEnd])
+ }, [floatingMenu, nodeStart, childs, nodeEnd])
}
renderJSONValue () {
@@ -214,38 +226,42 @@ export default class JSONNode extends PureComponent {
className: 'jsoneditor-node'
}, [
this.renderPlaceholder(),
- // this.renderDelimiter('\u2611'),
this.renderProperty(),
this.renderSeparator(),
this.renderValue(meta.value, meta.searchValue, this.props.options),
- // this.renderDelimiter('\u21B2'),
- // this.renderDelimiter('\u23CE'),
+ this.renderInsertAfter(),
this.renderError(meta.error)
])
const floatingMenu = this.renderFloatingMenu(MENU_ITEMS_VALUE, meta.selected)
- const insertArea = this.renderInsertBeforeArea()
+ // const insertArea = this.renderInsertBeforeArea()
return h('div', {
'data-path': compileJSONPointer(meta.path),
+ 'data-area': 'empty',
className: this.getContainerClassName(meta.selected, this.state.hover),
// onMouseOver: this.handleMouseOver,
// onMouseLeave: this.handleMouseLeave
- }, [node, floatingMenu, insertArea])
+ }, [node, floatingMenu])
}
- renderInsertBeforeArea () {
- const floatingMenu = ((this.props.value[META].selected & SELECTED_BEFORE) !== 0)
- ? this.renderFloatingMenu(MENU_ITEMS_INSERT_BEFORE,
- SELECTED + SELECTED_END + SELECTED_FIRST)
- : null
-
+ renderInsertBefore () {
return h('div', {
- key: 'menu',
- className: 'jsoneditor-insert-area',
+ key: 'insert',
+ className: 'jsoneditor-insert jsoneditor-insert-before',
+ title: 'Insert a new item or paste clipboard',
'data-area': 'before'
- }, [floatingMenu])
+ })
+ }
+
+ renderInsertAfter () {
+ return h('div', {
+ key: 'insert',
+ className: 'jsoneditor-insert jsoneditor-insert-after',
+ title: 'Insert a new item or paste clipboard after this line',
+ 'data-area': 'after'
+ })
}
/**
@@ -256,20 +272,30 @@ export default class JSONNode extends PureComponent {
renderAppend (text) {
return h('div', {
'data-path': compileJSONPointer(this.props.value[META].path) + '/-',
+ 'data-area': 'empty',
className: 'jsoneditor-node',
onKeyDown: this.handleKeyDownAppend
}, [
- this.renderPlaceholder(),
+ this.renderPlaceholder('before'),
this.renderReadonly(text)
])
}
- renderPlaceholder () {
- return h('div', {key: 'placeholder', className: 'jsoneditor-button-placeholder'})
+ renderPlaceholder (dataArea = 'value') {
+ return h('div', {
+ key: 'placeholder',
+ 'data-area': dataArea,
+ className: 'jsoneditor-button-placeholder'
+ })
}
- renderReadonly (text, title = null) {
- return h('div', {key: 'readonly', className: 'jsoneditor-readonly', title}, text)
+ renderReadonly (text, title = null, dataArea = 'before') {
+ return h('div', {
+ key: 'readonly',
+ 'data-area': dataArea,
+ className: 'jsoneditor-readonly',
+ title
+ }, text)
}
renderTag (text, title = null) {
@@ -302,7 +328,6 @@ export default class JSONNode extends PureComponent {
if (editable) {
return [
- // this.renderDelimiter('"'),
h('div', {
key: 'property',
className: 'jsoneditor-property' + emptyClassName + searchClassName,
@@ -311,7 +336,6 @@ export default class JSONNode extends PureComponent {
spellCheck: 'false',
onBlur: this.handleChangeProperty
}, escapedPropName),
- // this.renderDelimiter('" '),
]
}
else {
@@ -329,11 +353,19 @@ export default class JSONNode extends PureComponent {
return null
}
- return h('div', {key: 'separator', className: 'jsoneditor-delimiter'}, ':')
+ return h('div', {
+ key: 'separator',
+ className: 'jsoneditor-delimiter',
+ 'data-area': 'value'
+ }, ':')
}
renderDelimiter (text, className = '') {
- return h('div', {key: text, className: 'jsoneditor-delimiter ' + className}, text)
+ return h('div', {
+ key: text,
+ 'data-area': 'value',
+ className: 'jsoneditor-delimiter ' + className
+ }, text)
}
renderValue (value, searchResult, options) {
@@ -387,19 +419,31 @@ export default class JSONNode extends PureComponent {
getContainerClassName (selected, hover) {
let classNames = ['jsoneditor-node-container']
- if ((selected & SELECTED) !== 0) { classNames.push('jsoneditor-selected') }
- if ((selected & SELECTED_START) !== 0) { classNames.push('jsoneditor-selected-start') }
- if ((selected & SELECTED_END) !== 0) { classNames.push('jsoneditor-selected-end') }
- if ((selected & SELECTED_FIRST) !== 0) { classNames.push('jsoneditor-selected-first') }
- if ((selected & SELECTED_LAST) !== 0) { classNames.push('jsoneditor-selected-last') }
- if ((selected & SELECTED_BEFORE) !== 0) { classNames.push('jsoneditor-selected-insert-area-before') }
- if ((selected & SELECTED_AFTER) !== 0) { classNames.push('jsoneditor-selected-insert-area-after') }
+ if ((selected & SELECTED_BEFORE) !== 0) {
+ classNames.push('jsoneditor-selected-insert-before')
+ }
+ else if ((selected & SELECTED_AFTER) !== 0) {
+ classNames.push('jsoneditor-selected-insert-after')
+ }
+ else {
+ if ((selected & SELECTED) !== 0) { classNames.push('jsoneditor-selected') }
+ if ((selected & SELECTED_START) !== 0) { classNames.push('jsoneditor-selected-start') }
+ if ((selected & SELECTED_END) !== 0) { classNames.push('jsoneditor-selected-end') }
+ if ((selected & SELECTED_FIRST) !== 0) { classNames.push('jsoneditor-selected-first') }
+ if ((selected & SELECTED_LAST) !== 0) { classNames.push('jsoneditor-selected-last') }
+ }
- if ((hover & SELECTED) !== 0) { classNames.push('jsoneditor-hover') }
- if ((hover & SELECTED_START) !== 0) { classNames.push('jsoneditor-hover-start') }
- if ((hover & SELECTED_END) !== 0) { classNames.push('jsoneditor-hover-end') }
- if ((hover & SELECTED_BEFORE) !== 0) { classNames.push('jsoneditor-hover-insert-area-before') }
- if ((hover & SELECTED_AFTER) !== 0) { classNames.push('jsoneditor-hover-insert-area-after') }
+ if ((hover & SELECTED_BEFORE) !== 0) {
+ classNames.push('jsoneditor-hover-insert-before')
+ }
+ else if ((hover & SELECTED_AFTER) !== 0) {
+ classNames.push('jsoneditor-hover-insert-after')
+ }
+ else {
+ if ((hover & SELECTED) !== 0) { classNames.push('jsoneditor-hover') }
+ if ((hover & SELECTED_START) !== 0) { classNames.push('jsoneditor-hover-start') }
+ if ((hover & SELECTED_END) !== 0) { classNames.push('jsoneditor-hover-end') }
+ }
return classNames.join(' ')
}
diff --git a/src/jsoneditor/components/TreeMode.js b/src/jsoneditor/components/TreeMode.js
index c4fdc4f..86e8215 100644
--- a/src/jsoneditor/components/TreeMode.js
+++ b/src/jsoneditor/components/TreeMode.js
@@ -695,6 +695,9 @@ export default class TreeMode extends PureComponent {
const clickedOnEmptySpace = (event.target.nodeName === 'DIV') &&
(event.target.contentEditable !== 'true')
+ // TODO: cleanup
+ // console.log('handleTouchStart', clickedOnEmptySpace && pointer, pointer && this.selectionFromESONPointer(pointer))
+
if (clickedOnEmptySpace && pointer) {
this.setState({ selection: this.selectionFromESONPointer(pointer)})
}
@@ -707,9 +710,17 @@ export default class TreeMode extends PureComponent {
const selection = this.state.selection
const path = this.findDataPathFromElement(event.target.firstChild)
if (path && selection && !isEqual(path, selection.end)) {
+
+ // TODO: cleanup
+ // console.log('handlePan', {
+ // start: selection.start || selection.before || selection.after || selection.empty || selection.emptyBefore,
+ // end: path
+ // })
+
+ // FIXME: when selection.empty, start should be set to the next node
this.setState({
selection: {
- start: selection.start || selection.before || selection.after,
+ start: selection.start || selection.before || selection.after || selection.empty || selection.emptyBefore,
end: path
}
})
@@ -767,6 +778,12 @@ export default class TreeMode extends PureComponent {
else if (pointer.area === 'before') {
return {before: pointer.path}
}
+ else if (pointer.area === 'empty') {
+ return {empty: pointer.path}
+ }
+ else if (pointer.area === 'emptyBefore') {
+ return {emptyBefore: pointer.path}
+ }
else {
return {start: pointer.path, end: pointer.path}
}
diff --git a/src/jsoneditor/components/img/jsoneditor-icons.svg b/src/jsoneditor/components/img/jsoneditor-icons.svg
index 1b40068..81e172b 100644
--- a/src/jsoneditor/components/img/jsoneditor-icons.svg
+++ b/src/jsoneditor/components/img/jsoneditor-icons.svg
@@ -11,7 +11,7 @@
height="144"
id="svg4136"
version="1.1"
- inkscape:version="0.91 r"
+ inkscape:version="0.91 r13725"
sodipodi:docname="jsoneditor-icons.svg">
JSON Editor Icons
@@ -39,16 +39,16 @@
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
- inkscape:window-height="1028"
+ inkscape:window-height="1027"
id="namedview4144"
showgrid="true"
- inkscape:zoom="4"
- inkscape:cx="97.217248"
- inkscape:cy="59.950227"
+ inkscape:zoom="5.6568542"
+ inkscape:cx="113.02949"
+ inkscape:cy="98.794192"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
- inkscape:current-layer="svg4136"
+ inkscape:current-layer="g4394"
showguides="false"
borderlayer="false"
inkscape:showpageshadow="true"
@@ -67,7 +67,7 @@
width="16"
height="16"
id="svg_1"
- style="fill:#1aae1c;fill-opacity:1;stroke:none;stroke-width:0" />
+ style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
+
+
+
+
+
diff --git a/src/jsoneditor/components/jsoneditor.css b/src/jsoneditor/components/jsoneditor.css
index 1eda7a3..866cef0 100644
--- a/src/jsoneditor/components/jsoneditor.css
+++ b/src/jsoneditor/components/jsoneditor.css
@@ -168,6 +168,15 @@
display: inline-flex;
flex-direction: row; }
+.jsoneditor-node-end {
+ display: flex;
+ height: 20px; }
+ .jsoneditor-node-end .jsoneditor-button-container:hover {
+ visibility: visible; }
+
+.jsoneditor-root > .jsoneditor-node-container > .jsoneditor-node-end > .jsoneditor-button-container {
+ display: none; }
+
.jsoneditor-node > div {
flex: 0 0 auto; }
@@ -202,7 +211,8 @@ div.jsoneditor-list {
min-width: auto; }
.jsoneditor-button-container {
- font-size: 0; }
+ font-size: 0;
+ display: inline-block; }
.jsoneditor-property,
.jsoneditor-value {
@@ -240,6 +250,8 @@ div.jsoneditor-list {
.jsoneditor-delimiter-end {
padding-left: 5px;
border-left: 20px solid transparent; }
+ .jsoneditor-delimiter-end.jsoneditor-delimiter-collapsed {
+ border-left: none; }
.jsoneditor-readonly:focus,
.jsoneditor-readonly:hover {
@@ -355,193 +367,13 @@ button.jsoneditor-button.jsoneditor-actionmenu:focus,
button.jsoneditor-button.jsoneditor-actionmenu.jsoneditor-visible {
background-position: -50px -50px; }
-/******************************* Action Menu **********************************/
-div.jsoneditor-actionmenu {
- position: absolute;
- box-sizing: border-box;
- z-index: 99999;
- top: 20px;
- left: 18px;
- /* 20px - 2px where 2px half the difference between 24x24 icons of the menu and the 20x20 icons of the editor */
- background: white;
- border: 1px solid #d3d3d3;
- box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); }
-
-div.jsoneditor-actionmenu.jsoneditor-actionmenu-top {
- top: auto;
- bottom: 20px; }
-
-div.jsoneditor-modemenu.jsoneditor-modemenu {
- top: 26px;
- left: 0; }
-
-div.jsoneditor-menu-item {
- line-height: 0;
- font-size: 0; }
-
-button.jsoneditor-menu-button {
- width: 136px;
- height: 24px;
- padding: 0;
- margin: 0;
- line-height: 24px;
- background: transparent;
- border: transparent;
- display: inline-block;
- box-sizing: border-box;
- cursor: pointer;
- color: #4d4d4d;
- font-size: 10pt;
- font-family: arial, sans-serif;
- text-align: left; }
-
-button.jsoneditor-menu-button:hover,
-button.jsoneditor-menu-button:focus {
- color: #1A1A1A;
- background-color: #f5f5f5;
- outline: none; }
-
-button.jsoneditor-menu-button.jsoneditor-selected {
- color: white;
- background-color: #ee422e; }
-
-button.jsoneditor-menu-default {
- width: 104px;
- /* 136px - 32px */ }
-
-button.jsoneditor-menu-expand {
- width: 32px;
- float: right;
- border-left: 1px solid #e5e5e5; }
-
-span.jsoneditor-icon {
- float: left;
- width: 24px;
- height: 24px;
- border: none;
- padding: 0;
- margin: 0;
- background-image: url("img/jsoneditor-icons.svg"); }
-
-span.jsoneditor-icon.jsoneditor-icon-expand {
- float: right;
- width: 24px;
- margin: 0 4px;
- background-position: 0 -72px !important;
- opacity: 0.4; }
-
-div.jsoneditor-menu-item button.jsoneditor-menu-button:hover span.jsoneditor-icon-expand,
-div.jsoneditor-menu-item button:focus span.jsoneditor-icon-expand {
- opacity: 1; }
-
-span.jsoneditor-text {
- display: inline-block;
- line-height: 24px; }
-
-div.jsoneditor-menu-separator {
- height: 0;
- border-top: 1px solid #e5e5e5;
- padding-top: 5px;
- margin-top: 5px; }
-
+/*********************************** Menu *************************************/
div.jsoneditor-menu-panel-right {
float: right;
max-width: 100%; }
-button.jsoneditor-remove span.jsoneditor-icon {
- background-position: -24px -24px; }
-
-button.jsoneditor-remove:hover span.jsoneditor-icon,
-button.jsoneditor-remove:focus span.jsoneditor-icon {
- background-position: -24px 0; }
-
-button.jsoneditor-insert span.jsoneditor-icon {
- background-position: 0 -24px; }
-
-button.jsoneditor-insert:hover span.jsoneditor-icon,
-button.jsoneditor-insert:focus span.jsoneditor-icon {
- background-position: 0 0; }
-
-button.jsoneditor-duplicate span.jsoneditor-icon {
- background-position: -48px -24px; }
-
-button.jsoneditor-duplicate:hover span.jsoneditor-icon,
-button.jsoneditor-duplicate:focus span.jsoneditor-icon {
- background-position: -48px 0; }
-
-button.jsoneditor-sort-asc span.jsoneditor-icon {
- background-position: -168px -24px; }
-
-button.jsoneditor-sort-asc:hover span.jsoneditor-icon,
-button.jsoneditor-sort-asc:focus span.jsoneditor-icon {
- background-position: -168px 0; }
-
-button.jsoneditor-sort-desc span.jsoneditor-icon {
- background-position: -192px -24px; }
-
-button.jsoneditor-sort-desc:hover span.jsoneditor-icon,
-button.jsoneditor-sort-desc:focus span.jsoneditor-icon {
- background-position: -192px 0; }
-
-div.jsoneditor-submenu {
- visibility: hidden;
- max-height: 0;
- overflow: hidden;
- transition: max-height 0.3s ease-out;
- box-shadow: inset 0 10px 10px -10px rgba(128, 128, 128, 0.5), inset 0 -10px 10px -10px rgba(128, 128, 128, 0.5); }
-
-div.jsoneditor-submenu.jsoneditor-expanded {
- visibility: visible;
- max-height: 104px;
- /* 4 * 24px + 2 * 5px */
- /* FIXME: shouldn't rely on max-height equal to 4 items, should be flexible */ }
-
-div.jsoneditor-submenu.jsoneditor-collapsing {
- visibility: visible;
- max-height: 0; }
-
-div.jsoneditor-submenu button {
- padding-left: 24px; }
-
-div.jsoneditor-submenu div.jsoneditor-menu-item:first-child {
- margin-top: 5px; }
-
-div.jsoneditor-submenu div.jsoneditor-menu-item:last-child {
- margin-bottom: 5px; }
-
-button.jsoneditor-type-string span.jsoneditor-icon {
- background-position: -144px -24px; }
-
-button.jsoneditor-type-string:hover span.jsoneditor-icon,
-button.jsoneditor-type-string:focus span.jsoneditor-icon,
-button.jsoneditor-type-string.jsoneditor-selected span.jsoneditor-icon {
- background-position: -144px 0; }
-
-button.jsoneditor-type-value span.jsoneditor-icon {
- background-position: -120px -24px; }
-
-button.jsoneditor-type-value:hover span.jsoneditor-icon,
-button.jsoneditor-type-value:focus span.jsoneditor-icon,
-button.jsoneditor-type-value.jsoneditor-selected span.jsoneditor-icon {
- background-position: -120px 0; }
-
-button.jsoneditor-type-Object span.jsoneditor-icon {
- background-position: -72px -24px; }
-
-button.jsoneditor-type-Object:hover span.jsoneditor-icon,
-button.jsoneditor-type-Object:focus span.jsoneditor-icon,
-button.jsoneditor-type-Object.jsoneditor-selected span.jsoneditor-icon {
- background-position: -72px 0; }
-
-button.jsoneditor-type-Array span.jsoneditor-icon {
- background-position: -96px -24px; }
-
-button.jsoneditor-type-Array:hover span.jsoneditor-icon,
-button.jsoneditor-type-Array:focus span.jsoneditor-icon,
-button.jsoneditor-type-Array.jsoneditor-selected span.jsoneditor-icon {
- background-position: -96px 0; }
-
-/******************************* Floatting Menu **********************************/
+/******************************* Action Menu **********************************/
+/******************************* Floating Menu **********************************/
div.jsoneditor-node-container {
position: relative;
transition: background-color 100ms ease-in; }
@@ -568,6 +400,22 @@ div.jsoneditor-node-container {
border-left-color: #ffed99; }
div.jsoneditor-node-container.jsoneditor-selected .jsoneditor-list {
border-left-color: #ffed99; }
+ div.jsoneditor-node-container div.jsoneditor-insert {
+ width: 20px;
+ height: 20px; }
+ div.jsoneditor-node-container div.jsoneditor-insert:hover {
+ background: url("img/jsoneditor-icons.svg") -2px -26px; }
+ div.jsoneditor-node-container.jsoneditor-selected-insert-after {
+ border-bottom: 1px dashed #c0c0c0;
+ margin-bottom: -1px; }
+ div.jsoneditor-node-container.jsoneditor-selected-insert-after > .jsoneditor-node > .jsoneditor-insert-after,
+ div.jsoneditor-node-container.jsoneditor-selected-insert-after > .jsoneditor-node-end > .jsoneditor-insert-after {
+ background-image: url("img/jsoneditor-icons.svg");
+ background-position: -2px -2px !important; }
+ div.jsoneditor-node-container.jsoneditor-selected-insert-before > .jsoneditor-node > .jsoneditor-insert-before,
+ div.jsoneditor-node-container.jsoneditor-selected-insert-before > .jsoneditor-node-end > .jsoneditor-insert-before {
+ background-image: url("img/jsoneditor-icons.svg");
+ background-position: -2px -2px !important; }
div.jsoneditor-node-container.jsoneditor-hover > .jsoneditor-node > .jsoneditor-button-container,
div.jsoneditor-node-container.jsoneditor-hover > .jsoneditor-node > .jsoneditor-button-placeholder {
background-color: #d3d3d3; }
diff --git a/src/jsoneditor/components/jsoneditor.scss b/src/jsoneditor/components/jsoneditor.scss
index 5e17f6e..5aeadd9 100644
--- a/src/jsoneditor/components/jsoneditor.scss
+++ b/src/jsoneditor/components/jsoneditor.scss
@@ -123,6 +123,23 @@ $insert-area-height: 6px;
flex-direction: row;
}
+.jsoneditor-node-end {
+ display: flex;
+ height: $line-height;
+
+ .jsoneditor-button-container {
+ //visibility: hidden; // FIXME
+
+ &:hover {
+ visibility: visible;
+ }
+ }
+}
+
+.jsoneditor-root > .jsoneditor-node-container > .jsoneditor-node-end > .jsoneditor-button-container {
+ display: none;
+}
+
.jsoneditor-node > div {
flex: 0 0 auto;
}
@@ -167,6 +184,7 @@ div.jsoneditor-list {
.jsoneditor-button-container {
font-size: 0;
+ display: inline-block;
}
.jsoneditor-property,
@@ -218,6 +236,10 @@ div.jsoneditor-list {
.jsoneditor-delimiter-end {
padding-left: $input-padding;
border-left: $line-height solid transparent;
+
+ &.jsoneditor-delimiter-collapsed {
+ border-left: none;
+ }
}
.jsoneditor-readonly:focus,
@@ -362,241 +384,239 @@ button.jsoneditor-button.jsoneditor-actionmenu.jsoneditor-visible {
background-position: -50px -50px;
}
-
-
-/******************************* Action Menu **********************************/
-
-// TODO: move into a separate file like menu/Menu.less
-
-div.jsoneditor-actionmenu {
- position: absolute;
- box-sizing: border-box;
- z-index: 99999;
- top: 20px;
- left: 18px; /* 20px - 2px where 2px half the difference between 24x24 icons of the menu and the 20x20 icons of the editor */
- background: white;
-
- border: 1px solid #d3d3d3;
- box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
-}
-
-div.jsoneditor-actionmenu.jsoneditor-actionmenu-top {
- top: auto;
- bottom: 20px;
-}
-
-div.jsoneditor-modemenu.jsoneditor-modemenu {
- top: 26px;
- left: 0;
-}
-
-div.jsoneditor-menu-item {
- line-height: 0;
- font-size: 0;
-}
-
-button.jsoneditor-menu-button {
- width: 136px;
- height: 24px;
- padding: 0;
- margin: 0;
- line-height: 24px;
-
- background: transparent;
- border: transparent;
- display: inline-block;
- box-sizing: border-box;
-
- cursor: pointer;
- color: #4d4d4d;
-
- font-size: 10pt;
- font-family: arial, sans-serif;
- text-align: left;
-}
-
-button.jsoneditor-menu-button:hover,
-button.jsoneditor-menu-button:focus {
- color: $black;
- background-color: #f5f5f5;
- outline: none;
-}
-
-button.jsoneditor-menu-button.jsoneditor-selected {
- color: white;
- background-color: #ee422e;
-}
-
-button.jsoneditor-menu-default {
- width: 104px; /* 136px - 32px */
-}
-
-button.jsoneditor-menu-expand {
- width: 32px;
- float: right;
- border-left: 1px solid #e5e5e5;
-}
-
-span.jsoneditor-icon {
- float: left;
- width: 24px;
- height: 24px;
- border: none;
- padding: 0;
- margin: 0;
- background-image: url('img/jsoneditor-icons.svg');
-}
-
-span.jsoneditor-icon.jsoneditor-icon-expand {
- float: right;
- width: 24px;
- margin: 0 4px;
-
- background-position: 0 -72px !important;
- opacity: 0.4;
-}
-
-div.jsoneditor-menu-item button.jsoneditor-menu-button:hover span.jsoneditor-icon-expand,
-div.jsoneditor-menu-item button:focus span.jsoneditor-icon-expand {
- opacity: 1;
-}
-
-span.jsoneditor-text {
- display: inline-block;
- line-height: 24px;
-}
-
-div.jsoneditor-menu-separator {
- height: 0;
- border-top: 1px solid #e5e5e5;
- padding-top: 5px;
- margin-top: 5px;
-}
+/*********************************** Menu *************************************/
div.jsoneditor-menu-panel-right {
float: right;
max-width: 100%;
}
-button.jsoneditor-remove span.jsoneditor-icon {
- background-position: -24px -24px;
-}
-button.jsoneditor-remove:hover span.jsoneditor-icon,
-button.jsoneditor-remove:focus span.jsoneditor-icon {
- background-position: -24px 0;
-}
+/******************************* Action Menu **********************************/
-button.jsoneditor-insert span.jsoneditor-icon {
- background-position: 0 -24px;
-}
-button.jsoneditor-insert:hover span.jsoneditor-icon,
-button.jsoneditor-insert:focus span.jsoneditor-icon {
- background-position: 0 0;
-}
+// TODO: cleanup old ActionMenu css
+//div.jsoneditor-actionmenu {
+// position: absolute;
+// box-sizing: border-box;
+// z-index: 99999;
+// top: 20px;
+// left: 18px; /* 20px - 2px where 2px half the difference between 24x24 icons of the menu and the 20x20 icons of the editor */
+// background: white;
+//
+// border: 1px solid #d3d3d3;
+// box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
+//}
+//
+//div.jsoneditor-actionmenu.jsoneditor-actionmenu-top {
+// top: auto;
+// bottom: 20px;
+//}
+//
+//div.jsoneditor-modemenu.jsoneditor-modemenu {
+// top: 26px;
+// left: 0;
+//}
+//
+//div.jsoneditor-menu-item {
+// line-height: 0;
+// font-size: 0;
+//}
+//
+//button.jsoneditor-menu-button {
+// width: 136px;
+// height: 24px;
+// padding: 0;
+// margin: 0;
+// line-height: 24px;
+//
+// background: transparent;
+// border: transparent;
+// display: inline-block;
+// box-sizing: border-box;
+//
+// cursor: pointer;
+// color: #4d4d4d;
+//
+// font-size: 10pt;
+// font-family: arial, sans-serif;
+// text-align: left;
+//}
+//
+//button.jsoneditor-menu-button:hover,
+//button.jsoneditor-menu-button:focus {
+// color: $black;
+// background-color: #f5f5f5;
+// outline: none;
+//}
+//
+//button.jsoneditor-menu-button.jsoneditor-selected {
+// color: white;
+// background-color: #ee422e;
+//}
+//
+//button.jsoneditor-menu-default {
+// width: 104px; /* 136px - 32px */
+//}
+//
+//button.jsoneditor-menu-expand {
+// width: 32px;
+// float: right;
+// border-left: 1px solid #e5e5e5;
+//}
+//
+//span.jsoneditor-icon {
+// float: left;
+// width: 24px;
+// height: 24px;
+// border: none;
+// padding: 0;
+// margin: 0;
+// background-image: url('img/jsoneditor-icons.svg');
+//}
+//
+//span.jsoneditor-icon.jsoneditor-icon-expand {
+// float: right;
+// width: 24px;
+// margin: 0 4px;
+//
+// background-position: 0 -72px !important;
+// opacity: 0.4;
+//}
+//
+//div.jsoneditor-menu-item button.jsoneditor-menu-button:hover span.jsoneditor-icon-expand,
+//div.jsoneditor-menu-item button:focus span.jsoneditor-icon-expand {
+// opacity: 1;
+//}
+//
+//span.jsoneditor-text {
+// display: inline-block;
+// line-height: 24px;
+//}
+//
+//div.jsoneditor-menu-separator {
+// height: 0;
+// border-top: 1px solid #e5e5e5;
+// padding-top: 5px;
+// margin-top: 5px;
+//}
+//
+//button.jsoneditor-remove span.jsoneditor-icon {
+// background-position: -24px -24px;
+//}
+//button.jsoneditor-remove:hover span.jsoneditor-icon,
+//button.jsoneditor-remove:focus span.jsoneditor-icon {
+// background-position: -24px 0;
+//}
+//
+//button.jsoneditor-insert span.jsoneditor-icon {
+// background-position: 0 -24px;
+//}
+//button.jsoneditor-insert:hover span.jsoneditor-icon,
+//button.jsoneditor-insert:focus span.jsoneditor-icon {
+// background-position: 0 0;
+//}
+//
+//button.jsoneditor-duplicate span.jsoneditor-icon {
+// background-position: -48px -24px;
+//}
+//button.jsoneditor-duplicate:hover span.jsoneditor-icon,
+//button.jsoneditor-duplicate:focus span.jsoneditor-icon {
+// background-position: -48px 0;
+//}
+//
+//button.jsoneditor-sort-asc span.jsoneditor-icon {
+// background-position: -168px -24px;
+//}
+//button.jsoneditor-sort-asc:hover span.jsoneditor-icon,
+//button.jsoneditor-sort-asc:focus span.jsoneditor-icon {
+// background-position: -168px 0;
+//}
+//
+//button.jsoneditor-sort-desc span.jsoneditor-icon {
+// background-position: -192px -24px;
+//}
+//button.jsoneditor-sort-desc:hover span.jsoneditor-icon,
+//button.jsoneditor-sort-desc:focus span.jsoneditor-icon {
+// background-position: -192px 0;
+//}
+//
+//div.jsoneditor-submenu {
+// visibility: hidden;
+// max-height: 0;
+//
+// overflow: hidden;
+//
+// transition: max-height 0.3s ease-out;
+//
+// box-shadow: inset 0 10px 10px -10px rgba(128, 128, 128, 0.5),
+// inset 0 -10px 10px -10px rgba(128, 128, 128, 0.5)
+//}
+//
+//div.jsoneditor-submenu.jsoneditor-expanded {
+// visibility: visible;
+// max-height: 104px; /* 4 * 24px + 2 * 5px */
+// /* FIXME: shouldn't rely on max-height equal to 4 items, should be flexible */
+//}
+//
+//div.jsoneditor-submenu.jsoneditor-collapsing {
+// visibility: visible;
+// max-height: 0;
+//}
+//
+//div.jsoneditor-submenu button {
+// padding-left: 24px;
+//}
+//
+//div.jsoneditor-submenu div.jsoneditor-menu-item:first-child {
+// margin-top: 5px;
+//}
+//
+//div.jsoneditor-submenu div.jsoneditor-menu-item:last-child {
+// margin-bottom: 5px;
+//}
+//
+//button.jsoneditor-type-string span.jsoneditor-icon {
+// background-position: -144px -24px;
+//}
+//button.jsoneditor-type-string:hover span.jsoneditor-icon,
+//button.jsoneditor-type-string:focus span.jsoneditor-icon,
+//button.jsoneditor-type-string.jsoneditor-selected span.jsoneditor-icon {
+// background-position: -144px 0;
+//}
+//
+//button.jsoneditor-type-value span.jsoneditor-icon {
+// background-position: -120px -24px;
+//}
+//button.jsoneditor-type-value:hover span.jsoneditor-icon,
+//button.jsoneditor-type-value:focus span.jsoneditor-icon,
+//button.jsoneditor-type-value.jsoneditor-selected span.jsoneditor-icon {
+// background-position: -120px 0;
+//}
+//
+//button.jsoneditor-type-Object span.jsoneditor-icon {
+// background-position: -72px -24px;
+//}
+//button.jsoneditor-type-Object:hover span.jsoneditor-icon,
+//button.jsoneditor-type-Object:focus span.jsoneditor-icon,
+//button.jsoneditor-type-Object.jsoneditor-selected span.jsoneditor-icon {
+// background-position: -72px 0;
+//}
+//
+//button.jsoneditor-type-Array span.jsoneditor-icon {
+// background-position: -96px -24px;
+//}
+//button.jsoneditor-type-Array:hover span.jsoneditor-icon,
+//button.jsoneditor-type-Array:focus span.jsoneditor-icon,
+//button.jsoneditor-type-Array.jsoneditor-selected span.jsoneditor-icon {
+// background-position: -96px 0;
+//}
-button.jsoneditor-duplicate span.jsoneditor-icon {
- background-position: -48px -24px;
-}
-button.jsoneditor-duplicate:hover span.jsoneditor-icon,
-button.jsoneditor-duplicate:focus span.jsoneditor-icon {
- background-position: -48px 0;
-}
-
-button.jsoneditor-sort-asc span.jsoneditor-icon {
- background-position: -168px -24px;
-}
-button.jsoneditor-sort-asc:hover span.jsoneditor-icon,
-button.jsoneditor-sort-asc:focus span.jsoneditor-icon {
- background-position: -168px 0;
-}
-
-button.jsoneditor-sort-desc span.jsoneditor-icon {
- background-position: -192px -24px;
-}
-button.jsoneditor-sort-desc:hover span.jsoneditor-icon,
-button.jsoneditor-sort-desc:focus span.jsoneditor-icon {
- background-position: -192px 0;
-}
-
-div.jsoneditor-submenu {
- visibility: hidden;
- max-height: 0;
-
- overflow: hidden;
-
- transition: max-height 0.3s ease-out;
-
- box-shadow: inset 0 10px 10px -10px rgba(128, 128, 128, 0.5),
- inset 0 -10px 10px -10px rgba(128, 128, 128, 0.5)
-}
-
-div.jsoneditor-submenu.jsoneditor-expanded {
- visibility: visible;
- max-height: 104px; /* 4 * 24px + 2 * 5px */
- /* FIXME: shouldn't rely on max-height equal to 4 items, should be flexible */
-}
-
-div.jsoneditor-submenu.jsoneditor-collapsing {
- visibility: visible;
- max-height: 0;
-}
-
-div.jsoneditor-submenu button {
- padding-left: 24px;
-}
-
-div.jsoneditor-submenu div.jsoneditor-menu-item:first-child {
- margin-top: 5px;
-}
-
-div.jsoneditor-submenu div.jsoneditor-menu-item:last-child {
- margin-bottom: 5px;
-}
-
-button.jsoneditor-type-string span.jsoneditor-icon {
- background-position: -144px -24px;
-}
-button.jsoneditor-type-string:hover span.jsoneditor-icon,
-button.jsoneditor-type-string:focus span.jsoneditor-icon,
-button.jsoneditor-type-string.jsoneditor-selected span.jsoneditor-icon {
- background-position: -144px 0;
-}
-
-button.jsoneditor-type-value span.jsoneditor-icon {
- background-position: -120px -24px;
-}
-button.jsoneditor-type-value:hover span.jsoneditor-icon,
-button.jsoneditor-type-value:focus span.jsoneditor-icon,
-button.jsoneditor-type-value.jsoneditor-selected span.jsoneditor-icon {
- background-position: -120px 0;
-}
-
-button.jsoneditor-type-Object span.jsoneditor-icon {
- background-position: -72px -24px;
-}
-button.jsoneditor-type-Object:hover span.jsoneditor-icon,
-button.jsoneditor-type-Object:focus span.jsoneditor-icon,
-button.jsoneditor-type-Object.jsoneditor-selected span.jsoneditor-icon {
- background-position: -72px 0;
-}
-
-button.jsoneditor-type-Array span.jsoneditor-icon {
- background-position: -96px -24px;
-}
-button.jsoneditor-type-Array:hover span.jsoneditor-icon,
-button.jsoneditor-type-Array:focus span.jsoneditor-icon,
-button.jsoneditor-type-Array.jsoneditor-selected span.jsoneditor-icon {
- background-position: -96px 0;
-}
-
-/******************************* Floatting Menu **********************************/
+/******************************* Floating Menu **********************************/
div.jsoneditor-node-container {
position: relative;
transition: background-color 100ms ease-in;
- // TODO: can the hover/select css be simplified?
-
+ // TODO: cleanup insert-area css?
div.jsoneditor-insert-area {
//background: gray;
position: absolute;
@@ -656,6 +676,34 @@ div.jsoneditor-node-container {
}
}
+ div.jsoneditor-insert {
+ width: $line-height;
+ height: $line-height;
+
+ &:hover {
+ background: url('img/jsoneditor-icons.svg') -2px -26px;
+ }
+ }
+
+ &.jsoneditor-selected-insert-after {
+ border-bottom: 1px dashed $light-gray;
+ margin-bottom: -1px;
+
+ > .jsoneditor-node > .jsoneditor-insert-after,
+ > .jsoneditor-node-end > .jsoneditor-insert-after {
+ background-image: url('img/jsoneditor-icons.svg');
+ background-position: -2px -2px !important;
+ }
+ }
+
+ &.jsoneditor-selected-insert-before {
+ > .jsoneditor-node > .jsoneditor-insert-before,
+ > .jsoneditor-node-end > .jsoneditor-insert-before {
+ background-image: url('img/jsoneditor-icons.svg');
+ background-position: -2px -2px !important;
+ }
+ }
+
&.jsoneditor-hover {
> .jsoneditor-node > .jsoneditor-button-container,
> .jsoneditor-node > .jsoneditor-button-placeholder {
diff --git a/src/jsoneditor/eson.js b/src/jsoneditor/eson.js
index b8b6404..bc484c6 100644
--- a/src/jsoneditor/eson.js
+++ b/src/jsoneditor/eson.js
@@ -19,6 +19,8 @@ export const SELECTED_FIRST = 8
export const SELECTED_LAST = 16
export const SELECTED_BEFORE = 32
export const SELECTED_AFTER = 64
+export const SELECTED_EMPTY = 128
+export const SELECTED_EMPTY_BEFORE = 256
export const META = Symbol('meta')
@@ -361,14 +363,24 @@ export function applySelection (eson, selection) {
}
else if (selection.before) {
const updatedEson = setIn(eson, selection.before.concat([META, 'selected']),
- SELECTED + SELECTED_BEFORE)
+ SELECTED_BEFORE)
return cleanupMetaData(updatedEson, 'selected', [selection.before])
}
else if (selection.after) {
const updatedEson = setIn(eson, selection.after.concat([META, 'selected']),
- SELECTED + SELECTED_AFTER)
+ SELECTED_AFTER)
return cleanupMetaData(updatedEson, 'selected', [selection.after])
}
+ else if (selection.empty) {
+ const updatedEson = setIn(eson, selection.empty.concat([META, 'selected']),
+ SELECTED_EMPTY)
+ return cleanupMetaData(updatedEson, 'selected', [selection.empty])
+ }
+ else if (selection.emptyBefore) {
+ const updatedEson = setIn(eson, selection.emptyBefore.concat([META, 'selected']),
+ SELECTED_EMPTY_BEFORE)
+ return cleanupMetaData(updatedEson, 'selected', [selection.emptyBefore])
+ }
else { // selection.start and selection.end
// find the parent node shared by both start and end of the selection
const rootPath = findRootPath(selection)
@@ -556,6 +568,12 @@ export function findRootPath(selection) {
else if (selection.after) {
return initial(selection.after)
}
+ else if (selection.empty) {
+ return initial(selection.empty)
+ }
+ else if (selection.emptyBefore) {
+ return initial(selection.emptyBefore)
+ }
else { // selection.start and selection.end
const sharedPath = findSharedPath(selection.start, selection.end)
diff --git a/src/jsoneditor/types.js b/src/jsoneditor/types.js
index 7b12c45..c4080a5 100644
--- a/src/jsoneditor/types.js
+++ b/src/jsoneditor/types.js
@@ -42,7 +42,7 @@
*/
/**
- * @typedef {'value' | 'property'} ESONPointerArea
+ * @typedef {'value' | 'property' | 'before' | 'after' | 'empty'} ESONPointerArea
*/
/**