Implemented `transform` modal for modes `code` and `text`
This commit is contained in:
parent
74b816a554
commit
7311e78b53
|
@ -3,6 +3,11 @@
|
||||||
https://github.com/josdejong/jsoneditor
|
https://github.com/josdejong/jsoneditor
|
||||||
|
|
||||||
|
|
||||||
|
## not yet published, version 6.1.0
|
||||||
|
|
||||||
|
- Implemented menu options `sort` and `transform` for modes `code` and `text`.
|
||||||
|
|
||||||
|
|
||||||
## 2019-06-12, version 6.0.0
|
## 2019-06-12, version 6.0.0
|
||||||
|
|
||||||
- Breaking change: upgraded dependency `ajv@6.10.0`, supporting JSON schema
|
- Breaking change: upgraded dependency `ajv@6.10.0`, supporting JSON schema
|
||||||
|
|
|
@ -1459,7 +1459,7 @@ Node.prototype.changeType = function (newType) {
|
||||||
this.value = String(this.value);
|
this.value = String(this.value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.value = this._stringCast(String(this.value));
|
this.value = util.parseString(String(this.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.focus();
|
this.focus();
|
||||||
|
@ -1550,7 +1550,7 @@ Node.prototype._getDomValue = function() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var str = this._unescapeHTML(this.valueInnerText);
|
var str = this._unescapeHTML(this.valueInnerText);
|
||||||
value = this._stringCast(str);
|
value = util.parseString(str);
|
||||||
}
|
}
|
||||||
if (value !== this.value) {
|
if (value !== this.value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@ -4303,8 +4303,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
||||||
title: translate('transformTitle', {type: this.type}),
|
title: translate('transformTitle', {type: this.type}),
|
||||||
className: 'jsoneditor-transform',
|
className: 'jsoneditor-transform',
|
||||||
click: function () {
|
click: function () {
|
||||||
var anchor = node.editor.options.modalAnchor || DEFAULT_MODAL_ANCHOR;
|
node.showTransformModal();
|
||||||
showTransformModal(node, anchor)
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4456,7 +4455,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show advanced sorting modal
|
* Show sorting modal
|
||||||
*/
|
*/
|
||||||
Node.prototype.showSortModal = function () {
|
Node.prototype.showSortModal = function () {
|
||||||
var node = this;
|
var node = this;
|
||||||
|
@ -4479,6 +4478,19 @@ Node.prototype.showSortModal = function () {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show transform modal
|
||||||
|
*/
|
||||||
|
Node.prototype.showTransformModal = function () {
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
var anchor = this.editor.options.modalAnchor || DEFAULT_MODAL_ANCHOR;
|
||||||
|
var json = node.getValue();
|
||||||
|
showTransformModal(anchor, json, function (query) {
|
||||||
|
node.transform(query);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the type of a value
|
* get the type of a value
|
||||||
* @param {*} value
|
* @param {*} value
|
||||||
|
@ -4492,45 +4504,13 @@ Node.prototype._getType = function(value) {
|
||||||
if (value instanceof Object) {
|
if (value instanceof Object) {
|
||||||
return 'object';
|
return 'object';
|
||||||
}
|
}
|
||||||
if (typeof(value) == 'string' && typeof(this._stringCast(value)) != 'string') {
|
if (typeof(value) == 'string' && typeof(util.parseString(value)) != 'string') {
|
||||||
return 'string';
|
return 'string';
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'auto';
|
return 'auto';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
Node.prototype._stringCast = function(str) {
|
|
||||||
var lower = str.toLowerCase(),
|
|
||||||
num = Number(str), // will nicely fail with '123ab'
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* escape a text, such that it can be displayed safely in an HTML element
|
* escape a text, such that it can be displayed safely in an HTML element
|
||||||
* @param {String} text
|
* @param {String} text
|
||||||
|
|
|
@ -9,12 +9,14 @@ var MAX_PREVIEW_LINES = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show advanced filter and transform modal using JMESPath
|
* Show advanced filter and transform modal using JMESPath
|
||||||
* @param {Node} node the node to be transformed
|
|
||||||
* @param {HTMLElement} container The container where to center
|
* @param {HTMLElement} container The container where to center
|
||||||
* the modal and create an overlay
|
* 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 (node, container) {
|
function showTransformModal (container, json, onTransform) {
|
||||||
var value = node.getValue();
|
var value = json;
|
||||||
|
|
||||||
var content = '<label class="pico-modal-contents">' +
|
var content = '<label class="pico-modal-contents">' +
|
||||||
'<div class="pico-modal-header">' + translate('transform') + '</div>' +
|
'<div class="pico-modal-header">' + translate('transform') + '</div>' +
|
||||||
|
@ -119,8 +121,9 @@ function showTransformModal (node, container) {
|
||||||
wizard.innerHTML = '(wizard not available for objects, only for arrays)'
|
wizard.innerHTML = '(wizard not available for objects, only for arrays)'
|
||||||
}
|
}
|
||||||
|
|
||||||
var paths = node.getChildPaths();
|
var sortablePaths = util.getChildPaths(json);
|
||||||
paths.forEach(function (path) {
|
|
||||||
|
sortablePaths.forEach(function (path) {
|
||||||
var formattedPath = preprocessPath(path);
|
var formattedPath = preprocessPath(path);
|
||||||
var filterOption = document.createElement('option');
|
var filterOption = document.createElement('option');
|
||||||
filterOption.text = formattedPath;
|
filterOption.text = formattedPath;
|
||||||
|
@ -133,12 +136,11 @@ function showTransformModal (node, container) {
|
||||||
sortField.appendChild(sortOption);
|
sortField.appendChild(sortOption);
|
||||||
});
|
});
|
||||||
|
|
||||||
var allPaths = node.getChildPaths(true).filter(function(path) {
|
var selectablePaths = util.getChildPaths(json, true).filter(function(path) {
|
||||||
return path !== '.';
|
return path !== '.';
|
||||||
});
|
});
|
||||||
|
if (selectablePaths.length > 0) {
|
||||||
if (allPaths.length > 0) {
|
selectablePaths.forEach(function (path) {
|
||||||
allPaths.forEach(function (path) {
|
|
||||||
var formattedPath = preprocessPath(path);
|
var formattedPath = preprocessPath(path);
|
||||||
var option = document.createElement('option');
|
var option = document.createElement('option');
|
||||||
option.text = formattedPath;
|
option.text = formattedPath;
|
||||||
|
@ -194,10 +196,9 @@ function showTransformModal (node, container) {
|
||||||
? ['0'].concat(util.parsePath('.' + field1))
|
? ['0'].concat(util.parsePath('.' + field1))
|
||||||
: ['0']
|
: ['0']
|
||||||
var exampleValue = util.get(value, examplePath)
|
var exampleValue = util.get(value, examplePath)
|
||||||
// TODO: move _stringCast into a static util function
|
|
||||||
var value1 = typeof exampleValue === 'string'
|
var value1 = typeof exampleValue === 'string'
|
||||||
? filterValue.value
|
? filterValue.value
|
||||||
: node._stringCast(filterValue.value);
|
: parseString(filterValue.value);
|
||||||
|
|
||||||
query.value = '[? ' +
|
query.value = '[? ' +
|
||||||
field1 + ' ' +
|
field1 + ' ' +
|
||||||
|
@ -284,7 +285,7 @@ function showTransformModal (node, container) {
|
||||||
|
|
||||||
modal.close();
|
modal.close();
|
||||||
|
|
||||||
node.transform(query.value)
|
onTransform(query.value)
|
||||||
};
|
};
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var ace = require('./ace');
|
var ace = require('./ace');
|
||||||
|
var jmespath = require('jmespath');
|
||||||
var translate = require('./i18n').translate;
|
var translate = require('./i18n').translate;
|
||||||
var ModeSwitcher = require('./ModeSwitcher');
|
var ModeSwitcher = require('./ModeSwitcher');
|
||||||
var showSortModal = require('./showSortModal');
|
var showSortModal = require('./showSortModal');
|
||||||
|
@ -173,24 +174,23 @@ textmode.create = function (container, options) {
|
||||||
sort.className = 'jsoneditor-sort';
|
sort.className = 'jsoneditor-sort';
|
||||||
sort.title = translate('sortTitleShort');
|
sort.title = translate('sortTitleShort');
|
||||||
sort.onclick = function () {
|
sort.onclick = function () {
|
||||||
me._showSortModal()
|
me._showSortModal();
|
||||||
};
|
};
|
||||||
this.menu.appendChild(sort);
|
this.menu.appendChild(sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// // create transform button
|
// create transform button
|
||||||
// if (this.options.enableTransform) {
|
if (this.options.enableTransform) {
|
||||||
// var transform = document.createElement('button');
|
var transform = document.createElement('button');
|
||||||
// transform.type = 'button';
|
transform.type = 'button';
|
||||||
// transform.title = translate('transformTitleShort');
|
transform.title = translate('transformTitleShort');
|
||||||
// transform.className = 'jsoneditor-transform';
|
transform.className = 'jsoneditor-transform';
|
||||||
// transform.onclick = function () {
|
transform.onclick = function () {
|
||||||
// var anchor = me.options.modalAnchor || DEFAULT_MODAL_ANCHOR;
|
me._showTransformModal();
|
||||||
// showTransformModal(me.node, anchor)
|
};
|
||||||
// };
|
this.menu.appendChild(transform);
|
||||||
// this.menu.appendChild(transform);
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// create repair button
|
// create repair button
|
||||||
var buttonRepair = document.createElement('button');
|
var buttonRepair = document.createElement('button');
|
||||||
|
@ -468,6 +468,20 @@ textmode._showSortModal = function () {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a transform modal
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
textmode._showTransformModal = function () {
|
||||||
|
var me = this;
|
||||||
|
var anchor = this.options.modalAnchor || DEFAULT_MODAL_ANCHOR;
|
||||||
|
var json = this.get();
|
||||||
|
showTransformModal(anchor, json, function (query) {
|
||||||
|
var updatedJson = jmespath.search(json, query);
|
||||||
|
me.set(updatedJson);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle text selection
|
* Handle text selection
|
||||||
* Calculates the cursor position and selection range and updates menu
|
* Calculates the cursor position and selection range and updates menu
|
||||||
|
|
|
@ -10,13 +10,10 @@ var Node = require('./Node');
|
||||||
var ModeSwitcher = require('./ModeSwitcher');
|
var ModeSwitcher = require('./ModeSwitcher');
|
||||||
var util = require('./util');
|
var util = require('./util');
|
||||||
var autocomplete = require('./autocomplete');
|
var autocomplete = require('./autocomplete');
|
||||||
var showTransformModal = require('./showTransformModal');
|
|
||||||
var translate = require('./i18n').translate;
|
var translate = require('./i18n').translate;
|
||||||
var setLanguages = require('./i18n').setLanguages;
|
var setLanguages = require('./i18n').setLanguages;
|
||||||
var setLanguage = require('./i18n').setLanguage;
|
var setLanguage = require('./i18n').setLanguage;
|
||||||
|
|
||||||
var DEFAULT_MODAL_ANCHOR = document.body; // TODO: this constant is defined twice
|
|
||||||
|
|
||||||
// create a mixin with the functions for tree mode
|
// create a mixin with the functions for tree mode
|
||||||
var treemode = {};
|
var treemode = {};
|
||||||
|
|
||||||
|
@ -1033,8 +1030,7 @@ treemode._createFrame = function () {
|
||||||
transform.title = translate('transformTitleShort');
|
transform.title = translate('transformTitleShort');
|
||||||
transform.className = 'jsoneditor-transform';
|
transform.className = 'jsoneditor-transform';
|
||||||
transform.onclick = function () {
|
transform.onclick = function () {
|
||||||
var anchor = editor.options.modalAnchor || DEFAULT_MODAL_ANCHOR;
|
editor.node.showTransformModal();
|
||||||
showTransformModal(editor.node, anchor)
|
|
||||||
};
|
};
|
||||||
this.menu.appendChild(transform);
|
this.menu.appendChild(transform);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1264,6 +1264,38 @@ exports.sortObjectKeys = function (object, direction) {
|
||||||
return sortedObject;
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether a value is an Object
|
* Test whether a value is an Object
|
||||||
* @param {*} value
|
* @param {*} value
|
||||||
|
|
|
@ -353,6 +353,15 @@ describe('util', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should parse a string', function () {
|
||||||
|
assert.strictEqual(util.parseString('foo'), 'foo');
|
||||||
|
assert.strictEqual(util.parseString('234foo'), '234foo');
|
||||||
|
assert.strictEqual(util.parseString('2.3'), 2.3);
|
||||||
|
assert.strictEqual(util.parseString('null'), null);
|
||||||
|
assert.strictEqual(util.parseString('true'), true);
|
||||||
|
assert.strictEqual(util.parseString('false'), false);
|
||||||
|
})
|
||||||
|
|
||||||
it('should find a unique name', function () {
|
it('should find a unique name', function () {
|
||||||
assert.strictEqual(util.findUniqueName('other', [
|
assert.strictEqual(util.findUniqueName('other', [
|
||||||
'a',
|
'a',
|
||||||
|
|
Loading…
Reference in New Issue