Implemented advanced sorting modal (WIP)
This commit is contained in:
parent
9eb9c4fe0b
commit
8b77111393
|
@ -3,6 +3,11 @@
|
|||
https://github.com/josdejong/jsoneditor
|
||||
|
||||
|
||||
## not yet released, version 5.17.0
|
||||
|
||||
- Implemented advanced sorting for arrays.
|
||||
|
||||
|
||||
## 2018-05-23, version 5.16.0
|
||||
|
||||
- Better handling of JSON documents containing large arrays:
|
||||
|
|
|
@ -3676,6 +3676,11 @@
|
|||
"integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=",
|
||||
"dev": true
|
||||
},
|
||||
"picomodal": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picomodal/-/picomodal-3.0.0.tgz",
|
||||
"integrity": "sha1-+s0w9PvzSoCcHgTqUl8ATzmcC4I="
|
||||
},
|
||||
"posix-character-classes": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
"dependencies": {
|
||||
"ajv": "5.5.2",
|
||||
"brace": "0.11.0",
|
||||
"javascript-natural-sort": "0.7.1"
|
||||
"javascript-natural-sort": "0.7.1",
|
||||
"picomodal": "3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp": "3.9.1",
|
||||
|
|
|
@ -260,3 +260,47 @@ div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
|
|||
background-image: none;
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
|
||||
/* pico modal styling */
|
||||
|
||||
.jsoneditor-modal-overlay {
|
||||
position: absolute !important;
|
||||
|
||||
background: rgb(1,1,1) !important;
|
||||
opacity: 0.3 !important;
|
||||
}
|
||||
|
||||
.jsoneditor-modal {
|
||||
position: absolute !important;
|
||||
|
||||
border-radius: 2px !important;
|
||||
padding: 30px 20px 10px 20px !important;
|
||||
}
|
||||
|
||||
.jsoneditor-modal table td {
|
||||
padding: 5px 0;
|
||||
padding-right: 20px;
|
||||
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
font-size: 10pt;
|
||||
font-family: arial, sans-serif;
|
||||
}
|
||||
|
||||
.jsoneditor-modal table td:first-child {
|
||||
}
|
||||
|
||||
.jsoneditor-modal table td.jsoneditor-modal-input {
|
||||
text-align: right;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.jsoneditor-modal select {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.jsoneditor-modal .pico-close {
|
||||
background: none !important;
|
||||
font-size: 24px !important;
|
||||
}
|
|
@ -124,15 +124,15 @@ function History (editor) {
|
|||
'undo': function (params) {
|
||||
var node = params.node;
|
||||
node.hideChilds();
|
||||
node.sort = params.oldSort;
|
||||
node.childs = params.oldChilds;
|
||||
node._updateDomIndexes();
|
||||
node.showChilds();
|
||||
},
|
||||
'redo': function (params) {
|
||||
var node = params.node;
|
||||
node.hideChilds();
|
||||
node.sort = params.newSort;
|
||||
node.childs = params.newChilds;
|
||||
node._updateDomIndexes();
|
||||
node.showChilds();
|
||||
}
|
||||
}
|
||||
|
|
159
src/js/Node.js
159
src/js/Node.js
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var naturalSort = require('javascript-natural-sort');
|
||||
var picoModal = require('picomodal');
|
||||
var ContextMenu = require('./ContextMenu');
|
||||
var appendNodeFactory = require('./appendNodeFactory');
|
||||
var showMoreNodeFactory = require('./showMoreNodeFactory');
|
||||
|
@ -389,7 +390,7 @@ Node.prototype.setValue = function(value, type) {
|
|||
|
||||
// sort object keys
|
||||
if (this.editor.options.sortObjectKeys === true) {
|
||||
this.sort('asc');
|
||||
this.sort([], 'asc');
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -3096,29 +3097,42 @@ Node.prototype._onChangeType = function (newType) {
|
|||
/**
|
||||
* Sort the child's of the node. Only applicable when the node has type 'object'
|
||||
* or 'array'.
|
||||
* @param {String[]} path Path of the child value to be compared
|
||||
* @param {String} direction Sorting direction. Available values: "asc", "desc"
|
||||
* @private
|
||||
*/
|
||||
Node.prototype.sort = function (direction) {
|
||||
Node.prototype.sort = function (path, direction) {
|
||||
if (!this._hasChilds()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var order = (direction == 'desc') ? -1 : 1;
|
||||
var prop = (this.type == 'array') ? 'value': 'field';
|
||||
this.hideChilds();
|
||||
this.hideChilds(); // sorting is faster when the childs are not attached to the dom
|
||||
|
||||
// copy the childs array (the old one will be kept for an undo action
|
||||
var oldChilds = this.childs;
|
||||
var oldSortOrder = this.sortOrder;
|
||||
|
||||
// copy the array (the old one will be kept for an undo action
|
||||
this.childs = this.childs.concat();
|
||||
|
||||
// sort the arrays
|
||||
// sort the childs array
|
||||
var order = (direction === 'desc') ? -1 : 1;
|
||||
|
||||
if (this.type === 'object') {
|
||||
this.childs.sort(function (a, b) {
|
||||
return order * naturalSort(a[prop], b[prop]);
|
||||
return order * naturalSort(a.field, b.field);
|
||||
});
|
||||
this.sortOrder = (order == 1) ? 'asc' : 'desc';
|
||||
}
|
||||
else { // this.type === 'array'
|
||||
this.childs.sort(function (a, b) {
|
||||
var valueA = a.getNestedChild(path).value;
|
||||
var valueB = b.getNestedChild(path).value;
|
||||
|
||||
if (typeof valueA !== 'string' && typeof valueB !== 'string') {
|
||||
// both values are a number, boolean, or null
|
||||
return valueA > valueB ? order : valueA < valueB ? -order : 0;
|
||||
}
|
||||
|
||||
return order * naturalSort(valueA, valueB);
|
||||
});
|
||||
}
|
||||
|
||||
// update the index numbering
|
||||
this._updateDomIndexes();
|
||||
|
@ -3126,14 +3140,44 @@ Node.prototype.sort = function (direction) {
|
|||
this.editor._onAction('sort', {
|
||||
node: this,
|
||||
oldChilds: oldChilds,
|
||||
oldSort: oldSortOrder,
|
||||
newChilds: this.childs,
|
||||
newSort: this.sortOrder
|
||||
newChilds: this.childs
|
||||
});
|
||||
|
||||
this.showChilds();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a nested child given a path with properties
|
||||
* @param {String[]} path
|
||||
* @returns {Node}
|
||||
*/
|
||||
Node.prototype.getNestedChild = function (path) {
|
||||
var i = 0;
|
||||
var child = this;
|
||||
|
||||
while (child && i < path.length) {
|
||||
child = child.findChildByProperty(path[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
return child;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find a child by property name
|
||||
* @param {string} prop
|
||||
* @return {Node | undefined} Returns the child node when found, or undefined otherwise
|
||||
*/
|
||||
Node.prototype.findChildByProperty = function(prop) {
|
||||
if (this.type !== 'object') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.childs.find(function (child) {
|
||||
return child.field === prop;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the paths of the sortable child paths of this node
|
||||
* @return {Array}
|
||||
|
@ -3530,32 +3574,13 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
|
||||
if (this._hasChilds()) {
|
||||
var direction = ((this.sortOrder == 'asc') ? 'desc': 'asc');
|
||||
items.push({
|
||||
text: translate('sort'),
|
||||
title: translate('sortTitle') + this.type,
|
||||
className: 'jsoneditor-sort-' + direction,
|
||||
click: function () {
|
||||
node.sort(direction);
|
||||
},
|
||||
submenu: [
|
||||
{
|
||||
text: translate('ascending'),
|
||||
className: 'jsoneditor-sort-asc',
|
||||
title: translate('ascendingTitle' , {type: this.type}),
|
||||
click: function () {
|
||||
node.sort('asc');
|
||||
node._showSortModal()
|
||||
}
|
||||
},
|
||||
{
|
||||
text: translate('descending'),
|
||||
className: 'jsoneditor-sort-desc',
|
||||
title: translate('descendingTitle' , {type: this.type}),
|
||||
click: function () {
|
||||
node.sort('desc');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3693,6 +3718,72 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
menu.show(anchor, this.editor.content);
|
||||
};
|
||||
|
||||
/**
|
||||
* Show advanced sorting modal
|
||||
* @private
|
||||
*/
|
||||
Node.prototype._showSortModal = function () {
|
||||
var node = this;
|
||||
|
||||
picoModal({
|
||||
parent: this.editor.frame,
|
||||
content: '<div class="pico-modal-contents">' +
|
||||
'<form onsubmit="alert(1)">' +
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr>' +
|
||||
' <td>Sort by:</td>' +
|
||||
' <td class="jsoneditor-modal-input">' +
|
||||
' <select id="sortBy">' +
|
||||
' </select>' +
|
||||
' </td>' +
|
||||
'</tr>' +
|
||||
' <tr>' +
|
||||
' <td>Direction:</td>' +
|
||||
' <td class="jsoneditor-modal-input">' +
|
||||
' <select id="direction">' +
|
||||
' <option value="asc" selected>asc</option>' +
|
||||
' <option value="desc">desc</option>' +
|
||||
' </select>' +
|
||||
' </td>' +
|
||||
'</tr>' +
|
||||
'<tr>' +
|
||||
'<td colspan="2" class="jsoneditor-modal-input">' +
|
||||
' <button type="submit" id="ok">Sort</button>' +
|
||||
'</td>' +
|
||||
'</tr>' +
|
||||
'</tbody>' +
|
||||
'</table>' +
|
||||
'</form>' +
|
||||
'</div>',
|
||||
overlayClass: 'jsoneditor-modal-overlay',
|
||||
modalClass: 'jsoneditor-modal'
|
||||
})
|
||||
.afterCreate(function (modal) {
|
||||
var sortBy = modal.modalElem().querySelector('#sortBy');
|
||||
var direction = modal.modalElem().querySelector('#direction');
|
||||
var ok = modal.modalElem().querySelector('#ok');
|
||||
|
||||
node.getSortablePaths().forEach(function (path) {
|
||||
var pathStr = '.' + path.join('.');
|
||||
var option = document.createElement('option');
|
||||
option.text = pathStr;
|
||||
option.value = pathStr;
|
||||
sortBy.appendChild(option);
|
||||
});
|
||||
|
||||
ok.onclick = function () {
|
||||
modal.close();
|
||||
|
||||
var path = sortBy.value;
|
||||
var pathArray = (path === '.') ? [] : path.split('.').slice(1);
|
||||
|
||||
node.sort(pathArray, direction.value)
|
||||
};
|
||||
})
|
||||
.show();
|
||||
};
|
||||
|
||||
/**
|
||||
* get the type of a value
|
||||
* @param {*} value
|
||||
|
|
|
@ -33,9 +33,7 @@
|
|||
<code>editor.setMode(mode)</code>, try it in the console of your browser.
|
||||
</p>
|
||||
|
||||
<form>
|
||||
<div id="jsoneditor"></div>
|
||||
</form>
|
||||
<div id="jsoneditor"></div>
|
||||
|
||||
<script>
|
||||
var container = document.getElementById('jsoneditor');
|
||||
|
@ -70,7 +68,8 @@
|
|||
location: {
|
||||
latitude: 51 + i / 10000,
|
||||
longitude: 4 + i / 10000,
|
||||
}
|
||||
},
|
||||
random: Math.random()
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue