diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css
index 2bce9d1e16..13825119ce 100644
--- a/scripts/system/html/css/edit-style.css
+++ b/scripts/system/html/css/edit-style.css
@@ -1673,3 +1673,27 @@ input.number-slider {
.collapse-icon {
cursor: pointer;
}
+
+#property-userData-editor.error {
+ border: 2px solid red;
+}
+
+#property-userData-editorStatus {
+ color: white;
+ background-color: red;
+ padding: 5px;
+ display: none;
+ cursor: pointer;
+}
+
+#property-materialData-editor.error {
+ border: 2px solid red;
+}
+
+#property-materialData-editorStatus {
+ color: white;
+ background-color: red;
+ padding: 5px;
+ display: none;
+ cursor: pointer;
+}
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js
index da6a79d23a..84a1ab2a12 100644
--- a/scripts/system/html/js/entityProperties.js
+++ b/scripts/system/html/js/entityProperties.js
@@ -1431,13 +1431,13 @@ const TEXTURE_ELEMENTS = {
const JSON_EDITOR_ROW_DIV_INDEX = 2;
-var elGroups = {};
-var properties = {};
-var colorPickers = {};
-var particlePropertyUpdates = {};
-var selectedEntityProperties;
-var lastEntityID = null;
-var createAppTooltip = new CreateAppTooltip();
+let elGroups = {};
+let properties = {};
+let colorPickers = {};
+let particlePropertyUpdates = {};
+let selectedEntityProperties;
+let lastEntityID = null;
+let createAppTooltip = new CreateAppTooltip();
let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL;
function createElementFromHTML(htmlString) {
@@ -1691,7 +1691,7 @@ function updateProperty(originalPropertyName, propertyValue, isParticleProperty)
}
}
-var particleSyncDebounce = _.debounce(function () {
+let particleSyncDebounce = _.debounce(function () {
updateProperties(particlePropertyUpdates);
particlePropertyUpdates = {};
}, DEBOUNCE_TIMEOUT);
@@ -1825,7 +1825,7 @@ function createStringProperty(property, elProperty) {
type="text"
${propertyData.placeholder ? 'placeholder="' + propertyData.placeholder + '"' : ''}
${propertyData.readOnly ? 'readonly' : ''}>
- `)
+ `);
elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property));
@@ -2362,31 +2362,41 @@ function saveUserData() {
saveJSONUserData(true);
}
+function setJSONError(property, isError) {
+ $("#property-"+ property + "-editor").toggleClass('error', isError);
+ let $propertyUserDataEditorStatus = $("#property-"+ property + "-editorStatus");
+ $propertyUserDataEditorStatus.css('display', isError ? 'block' : 'none');
+ $propertyUserDataEditorStatus.text(isError ? 'Invalid JSON code - look for red X in your code' : '');
+}
+
function setUserDataFromEditor(noUpdate) {
let json = null;
+ let errorFound = false;
try {
json = editor.get();
} catch (e) {
- alert('Invalid JSON code - look for red X in your code ', +e);
+ errorFound = true;
}
- if (json === null) {
+
+ setJSONError('userData', errorFound);
+
+ if (errorFound) {
return;
+ }
+
+ let text = editor.getText();
+ if (noUpdate) {
+ EventBridge.emitWebEvent(
+ JSON.stringify({
+ id: lastEntityID,
+ type: "saveUserData",
+ properties: {
+ userData: text
+ }
+ })
+ );
} else {
- let text = editor.getText();
- if (noUpdate === true) {
- EventBridge.emitWebEvent(
- JSON.stringify({
- id: lastEntityID,
- type: "saveUserData",
- properties: {
- userData: text
- }
- })
- );
- return;
- } else {
- updateProperty('userData', text, false);
- }
+ updateProperty('userData', text, false);
}
}
@@ -2445,7 +2455,7 @@ function multiDataUpdater(groupName, updateKeyPair, userDataElement, defaults, r
updateProperties(propertyUpdate, false);
}
-var editor = null;
+let editor = null;
function createJSONEditor() {
let container = document.getElementById("property-userData-editor");
@@ -2508,9 +2518,10 @@ function hideUserDataSaved() {
function showStaticUserData() {
if (editor !== null) {
- $('#property-userData-static').show();
- $('#property-userData-static').css('height', $('#property-userData-editor').height());
- $('#property-userData-static').text(editor.getText());
+ let $propertyUserDataStatic = $('#property-userData-static');
+ $propertyUserDataStatic.show();
+ $propertyUserDataStatic.css('height', $('#property-userData-editor').height());
+ $propertyUserDataStatic.text(editor.getText());
}
}
@@ -2531,12 +2542,13 @@ function getEditorJSON() {
function deleteJSONEditor() {
if (editor !== null) {
+ setJSONError('userData', false);
editor.destroy();
editor = null;
}
}
-var savedJSONTimer = null;
+let savedJSONTimer = null;
function saveJSONUserData(noUpdate) {
setUserDataFromEditor(noUpdate);
@@ -2581,33 +2593,35 @@ function saveMaterialData() {
function setMaterialDataFromEditor(noUpdate) {
let json = null;
+ let errorFound = false;
try {
json = materialEditor.get();
} catch (e) {
- alert('Invalid JSON code - look for red X in your code ', +e);
+ errorFound = true;
}
- if (json === null) {
+
+ setJSONError('materialData', errorFound);
+
+ if (errorFound) {
return;
+ }
+ let text = materialEditor.getText();
+ if (noUpdate) {
+ EventBridge.emitWebEvent(
+ JSON.stringify({
+ id: lastEntityID,
+ type: "saveMaterialData",
+ properties: {
+ materialData: text
+ }
+ })
+ );
} else {
- let text = materialEditor.getText();
- if (noUpdate === true) {
- EventBridge.emitWebEvent(
- JSON.stringify({
- id: lastEntityID,
- type: "saveMaterialData",
- properties: {
- materialData: text
- }
- })
- );
- return;
- } else {
- updateProperty('materialData', text, false);
- }
+ updateProperty('materialData', text, false);
}
}
-var materialEditor = null;
+let materialEditor = null;
function createJSONMaterialEditor() {
let container = document.getElementById("property-materialData-editor");
@@ -2670,9 +2684,10 @@ function hideMaterialDataSaved() {
function showStaticMaterialData() {
if (materialEditor !== null) {
- $('#property-materialData-static').show();
- $('#property-materialData-static').css('height', $('#property-materialData-editor').height());
- $('#property-materialData-static').text(materialEditor.getText());
+ let $propertyMaterialDataStatic = $('#property-materialData-static');
+ $propertyMaterialDataStatic.show();
+ $propertyMaterialDataStatic.css('height', $('#property-materialData-editor').height());
+ $propertyMaterialDataStatic.text(materialEditor.getText());
}
}
@@ -2693,12 +2708,13 @@ function getMaterialEditorJSON() {
function deleteJSONMaterialEditor() {
if (materialEditor !== null) {
+ setJSONError('materialData', false);
materialEditor.destroy();
materialEditor = null;
}
}
-var savedMaterialJSONTimer = null;
+let savedMaterialJSONTimer = null;
function saveJSONMaterialData(noUpdate) {
setMaterialDataFromEditor(noUpdate);
@@ -2958,7 +2974,7 @@ function loaded() {
let elServerScriptError = document.getElementById("property-serverScripts-error");
let elServerScriptStatus = document.getElementById("property-serverScripts-status");
elServerScriptError.value = data.errorInfo;
- // If we just set elServerScriptError's diplay to block or none, we still end up with
+ // If we just set elServerScriptError's display to block or none, we still end up with
// it's parent contributing 21px bottom padding even when elServerScriptError is display:none.
// So set it's parent to block or none
elServerScriptError.parentElement.style.display = data.errorInfo ? "block" : "none";
@@ -3317,12 +3333,15 @@ function loaded() {
elStaticUserData.setAttribute("id", userDataElementID + "-static");
let elUserDataEditor = document.createElement('div');
elUserDataEditor.setAttribute("id", userDataElementID + "-editor");
+ let elUserDataEditorStatus = document.createElement('div');
+ elUserDataEditorStatus.setAttribute("id", userDataElementID + "-editorStatus");
let elUserDataSaved = document.createElement('span');
elUserDataSaved.setAttribute("id", userDataElementID + "-saved");
elUserDataSaved.innerText = "Saved!";
elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elUserDataSaved);
elDiv.insertBefore(elStaticUserData, elUserData);
elDiv.insertBefore(elUserDataEditor, elUserData);
+ elDiv.insertBefore(elUserDataEditorStatus, elUserData);
// Material Data
let materialDataProperty = properties["materialData"];
@@ -3333,12 +3352,15 @@ function loaded() {
elStaticMaterialData.setAttribute("id", materialDataElementID + "-static");
let elMaterialDataEditor = document.createElement('div');
elMaterialDataEditor.setAttribute("id", materialDataElementID + "-editor");
+ let elMaterialDataEditorStatus = document.createElement('div');
+ elMaterialDataEditorStatus.setAttribute("id", materialDataElementID + "-editorStatus");
let elMaterialDataSaved = document.createElement('span');
elMaterialDataSaved.setAttribute("id", materialDataElementID + "-saved");
elMaterialDataSaved.innerText = "Saved!";
elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elMaterialDataSaved);
elDiv.insertBefore(elStaticMaterialData, elMaterialData);
elDiv.insertBefore(elMaterialDataEditor, elMaterialData);
+ elDiv.insertBefore(elMaterialDataEditorStatus, elMaterialData);
// Special Property Callbacks
let elParentMaterialNameString = getPropertyInputElement("materialNameToReplace");