Skip to content

Commit

Permalink
Fix #926: Keep order of properties when updating an object
Browse files Browse the repository at this point in the history
  • Loading branch information
josdejong committed Mar 18, 2020
1 parent 341cc2c commit 2316c87
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 20 deletions.
2 changes: 1 addition & 1 deletion HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

https://github.com/josdejong/jsoneditor


## not yet published, version 8.6.2

- Fixed #926: Keep order of properties when updating an object.
- Fixed #928: Custom root name not reflected in path of navigation bar.
- Upgraded to `ajv@6.12.0`

Expand Down
42 changes: 28 additions & 14 deletions src/js/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ export class Node {
setValue (value, type) {
let childValue, child, visible
let i, j
const notUpdateDom = false
const updateDom = false
const previousChilds = this.childs

this.type = this._getType(value)
Expand Down Expand Up @@ -454,15 +454,15 @@ export class Node {
value: childValue
})
visible = i < this.getMaxVisibleChilds()
this.appendChild(child, visible, notUpdateDom)
this.appendChild(child, visible, updateDom)
}
}
}

// cleanup redundant childs
// we loop backward to prevent issues with shifting index numbers
for (j = this.childs.length; j >= value.length; j--) {
this.removeChild(this.childs[j], notUpdateDom)
this.removeChild(this.childs[j], updateDom)
}
} else if (this.type === 'object') {
// object
Expand All @@ -474,7 +474,7 @@ export class Node {
// we loop backward to prevent issues with shifting index numbers
for (j = this.childs.length - 1; j >= 0; j--) {
if (!hasOwnProperty(value, this.childs[j].field)) {
this.removeChild(this.childs[j], notUpdateDom)
this.removeChild(this.childs[j], updateDom)
}
}

Expand All @@ -483,20 +483,25 @@ export class Node {
if (hasOwnProperty(value, childField)) {
childValue = value[childField]
if (childValue !== undefined && !(childValue instanceof Function)) {
child = this.findChildByProperty(childField)
const childIndex = this.childs.findIndex(child => child.field === childField)
child = this.childs[childIndex]

if (child) {
// reuse existing child, keep its state
child.setField(childField, true)
child.setValue(childValue)

// change the index of the property such that it matches the index of the updated JSON
if (childIndex !== i) {
this.moveBefore(child, this.childs[i])
}
} else {
// create a new child
child = new Node(this.editor, {
field: childField,
value: childValue
})
visible = i < this.getMaxVisibleChilds()
this.appendChild(child, visible, notUpdateDom)
this.insertBefore(child, this.childs[i], updateDom)
}
}
i++
Expand Down Expand Up @@ -1012,8 +1017,11 @@ export class Node {
* Only applicable when Node value is of type array or object
* @param {Node} node
* @param {Node} beforeNode
* @param {boolean} [updateDom] If true (default), the DOM of both parent
* node and appended node will be updated
* (child count, indexes)
*/
moveBefore (node, beforeNode) {
moveBefore (node, beforeNode, updateDom) {
if (this._hasChilds()) {
// create a temporary row, to prevent the scroll position from jumping
// when removing the node
Expand All @@ -1032,12 +1040,13 @@ export class Node {
// the this.childs.length + 1 is to reckon with the node that we're about to add
if (this.childs.length + 1 > this.visibleChilds) {
const lastVisibleNode = this.childs[this.visibleChilds - 1]
this.insertBefore(node, lastVisibleNode)
this.insertBefore(node, lastVisibleNode, updateDom)
} else {
this.appendChild(node)
const visible = true
this.appendChild(node, visible, updateDom)
}
} else {
this.insertBefore(node, beforeNode)
this.insertBefore(node, beforeNode, updateDom)
}

if (tbody) {
Expand All @@ -1051,8 +1060,11 @@ export class Node {
* Only applicable when Node value is of type array or object
* @param {Node} node
* @param {Node} beforeNode
* @param {boolean} [updateDom] If true (default), the DOM of both parent
* node and appended node will be updated
* (child count, indexes)
*/
insertBefore (node, beforeNode) {
insertBefore (node, beforeNode, updateDom) {
if (this._hasChilds()) {
this.visibleChilds++

Expand Down Expand Up @@ -1094,8 +1106,10 @@ export class Node {
this.showChilds()
}

this.updateDom({ updateIndexes: true })
node.updateDom({ recurse: true })
if (updateDom !== false) {
this.updateDom({ updateIndexes: true })
node.updateDom({ recurse: true })
}
}
}

Expand Down
20 changes: 15 additions & 5 deletions src/js/polyfills.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,26 @@ if (typeof Element !== 'undefined') {
})()
}

// Polyfill for Array.find
if (!Array.prototype.find) {
// simple polyfill for Array.findIndex
if (!Array.prototype.findIndex) {
// eslint-disable-next-line no-extend-native
Array.prototype.find = function (callback) {
Array.prototype.findIndex = function (predicate) {
for (let i = 0; i < this.length; i++) {
const element = this[i]
if (callback.call(this, element, i, this)) {
return element
if (predicate.call(this, element, i, this)) {
return i
}
}
return -1
}
}

// Polyfill for Array.find
if (!Array.prototype.find) {
// eslint-disable-next-line no-extend-native
Array.prototype.find = function (predicate) {
const i = this.findIndex(predicate)
return this[i]
}
}

Expand Down

0 comments on commit 2316c87

Please sign in to comment.