This commit is contained in:
parent
036c9e1914
commit
f86f3d4e1c
|
@ -3,8 +3,10 @@
|
||||||
https://github.com/josdejong/jsoneditor
|
https://github.com/josdejong/jsoneditor
|
||||||
|
|
||||||
|
|
||||||
## not yet published, version 8.0.1
|
## not yet published, version 8.1.0
|
||||||
|
|
||||||
|
- Implemented `popupAnchor` allowing to select a custom anchor element.
|
||||||
|
See #869 and #870.
|
||||||
- Fixed #502: CSS rule `* { font-family: ... }` resulting in Ace editor (`code`
|
- Fixed #502: CSS rule `* { font-family: ... }` resulting in Ace editor (`code`
|
||||||
mode) not having a mono-space font anymore.
|
mode) not having a mono-space font anymore.
|
||||||
|
|
||||||
|
|
11
docs/api.md
11
docs/api.md
|
@ -567,6 +567,17 @@ Constructs a new JSONEditor.
|
||||||
The container element where modals (like for sorting and filtering) are attached: an overlay will be created on top
|
The container element where modals (like for sorting and filtering) are attached: an overlay will be created on top
|
||||||
of this container, and the modal will be created in the center of this container.
|
of this container, and the modal will be created in the center of this container.
|
||||||
|
|
||||||
|
- `{HTMLElement} popupAnchor`
|
||||||
|
|
||||||
|
The container element where popups (for example drop down menus, for JSON Schema error
|
||||||
|
tooltips, and color pickers) will be absolutely positioned.
|
||||||
|
By default, this is the root DIV element of the editor itself.
|
||||||
|
|
||||||
|
When the JSONEditor is inside a DIV element which hides overflowing contents
|
||||||
|
(CSS `overflow: auto` or `overflow: hidden`), tooltips will be visible only partly.
|
||||||
|
In this case, a `popupAnchor` outside of the element without hidden overflow will allow
|
||||||
|
the tooltips to be visible when overflowing the DIV element of the JSONEditor.
|
||||||
|
|
||||||
- `{boolean} enableSort`
|
- `{boolean} enableSort`
|
||||||
|
|
||||||
Enable sorting of arrays and object properties. Only applicable for mode 'tree'. `true` by default.
|
Enable sorting of arrays and object properties. Only applicable for mode 'tree'. `true` by default.
|
||||||
|
|
|
@ -183,7 +183,8 @@ JSONEditor.VALID_OPTIONS = [
|
||||||
'timestampTag', 'timestampFormat',
|
'timestampTag', 'timestampFormat',
|
||||||
'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation',
|
'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation',
|
||||||
'sortObjectKeys', 'navigationBar', 'statusBar', 'mainMenuBar', 'languages', 'language', 'enableSort', 'enableTransform',
|
'sortObjectKeys', 'navigationBar', 'statusBar', 'mainMenuBar', 'languages', 'language', 'enableSort', 'enableTransform',
|
||||||
'maxVisibleChilds', 'onValidationError'
|
'maxVisibleChilds', 'onValidationError',
|
||||||
|
'modalAnchor', 'popupAnchor'
|
||||||
]
|
]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -303,7 +303,7 @@ export class Node {
|
||||||
|
|
||||||
const createPopup = (destroyOnMouseOut) => {
|
const createPopup = (destroyOnMouseOut) => {
|
||||||
const frame = this.editor.frame
|
const frame = this.editor.frame
|
||||||
this.dom.popupAnchor = createAbsoluteAnchor(button, frame, onDestroy, destroyOnMouseOut)
|
this.dom.popupAnchor = createAbsoluteAnchor(button, this.editor.getPopupAnchor(), onDestroy, destroyOnMouseOut)
|
||||||
|
|
||||||
const popupWidth = 200 // must correspond to what's configured in the CSS
|
const popupWidth = 200 // must correspond to what's configured in the CSS
|
||||||
const buttonRect = button.getBoundingClientRect()
|
const buttonRect = button.getBoundingClientRect()
|
||||||
|
@ -3021,7 +3021,7 @@ export class Node {
|
||||||
node._deleteDomColor()
|
node._deleteDomColor()
|
||||||
node.updateDom()
|
node.updateDom()
|
||||||
|
|
||||||
const colorAnchor = createAbsoluteAnchor(this.dom.color, this.editor.frame)
|
const colorAnchor = createAbsoluteAnchor(this.dom.color, this.editor.getPopupAnchor())
|
||||||
|
|
||||||
this.editor.options.onColorPicker(colorAnchor, this.value, function onChange (value) {
|
this.editor.options.onColorPicker(colorAnchor, this.value, function onChange (value) {
|
||||||
if (typeof value === 'string' && value !== node.value) {
|
if (typeof value === 'string' && value !== node.value) {
|
||||||
|
@ -3835,7 +3835,7 @@ export class Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = new ContextMenu(items, { close: onClose })
|
const menu = new ContextMenu(items, { close: onClose })
|
||||||
menu.show(anchor, this.editor.frame)
|
menu.show(anchor, this.editor.getPopupAnchor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -207,7 +207,7 @@ export function appendNodeFactory (Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = new ContextMenu(items, { close: onClose })
|
const menu = new ContextMenu(items, { close: onClose })
|
||||||
menu.show(anchor, this.editor.frame)
|
menu.show(anchor, this.editor.getPopupAnchor())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,13 +14,13 @@ export function createAbsoluteAnchor (anchor, parent, onDestroy, destroyOnMouseO
|
||||||
const eventListeners = {}
|
const eventListeners = {}
|
||||||
|
|
||||||
const anchorRect = anchor.getBoundingClientRect()
|
const anchorRect = anchor.getBoundingClientRect()
|
||||||
const frameRect = parent.getBoundingClientRect()
|
const parentRect = parent.getBoundingClientRect()
|
||||||
|
|
||||||
const absoluteAnchor = document.createElement('div')
|
const absoluteAnchor = document.createElement('div')
|
||||||
absoluteAnchor.className = 'jsoneditor-anchor'
|
absoluteAnchor.className = 'jsoneditor-anchor'
|
||||||
absoluteAnchor.style.position = 'absolute'
|
absoluteAnchor.style.position = 'absolute'
|
||||||
absoluteAnchor.style.left = (anchorRect.left - frameRect.left) + 'px'
|
absoluteAnchor.style.left = (anchorRect.left - parentRect.left) + 'px'
|
||||||
absoluteAnchor.style.top = (anchorRect.top - frameRect.top) + 'px'
|
absoluteAnchor.style.top = (anchorRect.top - parentRect.top) + 'px'
|
||||||
absoluteAnchor.style.width = (anchorRect.width - 2) + 'px'
|
absoluteAnchor.style.width = (anchorRect.width - 2) + 'px'
|
||||||
absoluteAnchor.style.height = (anchorRect.height - 2) + 'px'
|
absoluteAnchor.style.height = (anchorRect.height - 2) + 'px'
|
||||||
absoluteAnchor.style.boxSizing = 'border-box'
|
absoluteAnchor.style.boxSizing = 'border-box'
|
||||||
|
|
|
@ -135,13 +135,12 @@ treemode._setOptions = function (options) {
|
||||||
const pickerHeight = 300 // estimated height of the color picker
|
const pickerHeight = 300 // estimated height of the color picker
|
||||||
const top = parent.getBoundingClientRect().top
|
const top = parent.getBoundingClientRect().top
|
||||||
const windowHeight = window.innerHeight
|
const windowHeight = window.innerHeight
|
||||||
|
const showOnTop = ((windowHeight - top) < pickerHeight && top > pickerHeight)
|
||||||
|
|
||||||
new VanillaPicker({
|
new VanillaPicker({
|
||||||
parent: parent,
|
parent: parent,
|
||||||
color: color,
|
color: color,
|
||||||
popup: ((windowHeight - top) < pickerHeight && top > pickerHeight)
|
popup: showOnTop ? 'top' : 'bottom',
|
||||||
? 'top'
|
|
||||||
: 'bottom',
|
|
||||||
onDone: function (color) {
|
onDone: function (color) {
|
||||||
const alpha = color.rgba[3]
|
const alpha = color.rgba[3]
|
||||||
const hex = (alpha === 1)
|
const hex = (alpha === 1)
|
||||||
|
@ -1063,7 +1062,7 @@ treemode._createFrame = function () {
|
||||||
this.navBar.className = 'jsoneditor-navigation-bar nav-bar-empty'
|
this.navBar.className = 'jsoneditor-navigation-bar nav-bar-empty'
|
||||||
this.frame.appendChild(this.navBar)
|
this.frame.appendChild(this.navBar)
|
||||||
|
|
||||||
this.treePath = new TreePath(this.navBar, this.frame)
|
this.treePath = new TreePath(this.navBar, this.getPopupAnchor())
|
||||||
this.treePath.onSectionSelected(this._onTreePathSectionSelected.bind(this))
|
this.treePath.onSectionSelected(this._onTreePathSectionSelected.bind(this))
|
||||||
this.treePath.onContextMenuItemSelected(this._onTreePathMenuItemSelected.bind(this))
|
this.treePath.onContextMenuItemSelected(this._onTreePathMenuItemSelected.bind(this))
|
||||||
}
|
}
|
||||||
|
@ -1681,7 +1680,11 @@ treemode.showContextMenu = function (anchor, onClose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = new ContextMenu(items, { close: onClose })
|
const menu = new ContextMenu(items, { close: onClose })
|
||||||
menu.show(anchor, this.frame)
|
menu.show(anchor, this.getPopupAnchor())
|
||||||
|
}
|
||||||
|
|
||||||
|
treemode.getPopupAnchor = function () {
|
||||||
|
return this.options.popupAnchor || this.frame
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>JSONEditor | JSON schema validation</title>
|
||||||
|
|
||||||
|
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
|
||||||
|
<script src="../dist/jsoneditor.js"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
width: 600px;
|
||||||
|
font: 11pt sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#anchor {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#jsoneditor {
|
||||||
|
width: 320px;
|
||||||
|
height: 300px;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* custom bold styling for non-default JSON schema values */
|
||||||
|
.jsoneditor-is-not-default {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Test custom tooltip anchor</h1>
|
||||||
|
<p>
|
||||||
|
The JSON Schema error tooltips and the color picker should have correct placing and overflow the editor, also in combination with scrolling.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div id="anchor">
|
||||||
|
<div id="jsoneditor"></div>
|
||||||
|
</div>
|
||||||
|
<div style="height: 2000px"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const schema = {
|
||||||
|
"title": "Employee",
|
||||||
|
"description": "Object containing employee details",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"firstName": {
|
||||||
|
"title": "First Name",
|
||||||
|
"description": "The given name.",
|
||||||
|
"examples": [
|
||||||
|
"John"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"title": "Last Name",
|
||||||
|
"description": "The family name.",
|
||||||
|
"examples": [
|
||||||
|
"Smith"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"gender": {
|
||||||
|
"title": "Gender",
|
||||||
|
"enum": ["male", "female"]
|
||||||
|
},
|
||||||
|
"availableToHire": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"age": {
|
||||||
|
"description": "Age in years",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"examples": [28, 32]
|
||||||
|
},
|
||||||
|
"job": {
|
||||||
|
"$ref": "job"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["firstName", "lastName"]
|
||||||
|
}
|
||||||
|
|
||||||
|
const job = {
|
||||||
|
"title": "Job description",
|
||||||
|
"type": "object",
|
||||||
|
"required": ["address"],
|
||||||
|
"properties": {
|
||||||
|
"company": {
|
||||||
|
"type": "string",
|
||||||
|
"examples": [
|
||||||
|
"ACME",
|
||||||
|
"Dexter Industries"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"description": "Job title.",
|
||||||
|
"type": "string",
|
||||||
|
"examples": [
|
||||||
|
"Human Resources Coordinator",
|
||||||
|
"Software Developer"
|
||||||
|
],
|
||||||
|
"default": "Software Developer"
|
||||||
|
},
|
||||||
|
"address": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"salary": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 120,
|
||||||
|
"examples": [100, 110, 120]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const json = {
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
gender: null,
|
||||||
|
age: "28",
|
||||||
|
availableToHire: true,
|
||||||
|
favoriteColor: 'red',
|
||||||
|
job: {
|
||||||
|
company: 'freelance',
|
||||||
|
role: 'developer',
|
||||||
|
salary: 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
schema: schema,
|
||||||
|
schemaRefs: {"job": job},
|
||||||
|
mode: 'tree',
|
||||||
|
modes: ['code', 'text', 'tree', 'preview'],
|
||||||
|
popupAnchor: document.getElementById('anchor')
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the editor
|
||||||
|
const container = document.getElementById('jsoneditor')
|
||||||
|
const editor = new JSONEditor(container, options, json)
|
||||||
|
editor.expandAll()
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue