mirror of
https://github.com/Karaka-Management/jsOMS.git
synced 2026-02-11 07:08:40 +00:00
implement inline update/save functionality
This commit is contained in:
parent
72e6c97965
commit
3d0fbc5778
|
|
@ -692,7 +692,8 @@ export class Form
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert row values data into form
|
// insert row values data into form
|
||||||
length = values.length;
|
const remoteValueUrls = {};
|
||||||
|
length = values.length;
|
||||||
for (let i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
const path = values[i].hasAttribute('data-tpl-value-path') ? values[i].getAttribute('data-tpl-value-path') : null;
|
const path = values[i].hasAttribute('data-tpl-value-path') ? values[i].getAttribute('data-tpl-value-path') : null;
|
||||||
for (let j = 0; j < selectorLength; ++j) {
|
for (let j = 0; j < selectorLength; ++j) {
|
||||||
|
|
@ -712,21 +713,11 @@ export class Form
|
||||||
? document.getElementsByTagName('base')[0].href
|
? document.getElementsByTagName('base')[0].href
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
const request = new Request(uri + values[i].getAttribute('data-tpl-value'));
|
if (remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')] === undefined) {
|
||||||
request.setResultCallback(200, function(xhr) {
|
remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')] = [];
|
||||||
/**
|
}
|
||||||
* @todo Orange-Management/jsOMS#84
|
|
||||||
* Remote data responses need to be parsed
|
|
||||||
* The data coming from the backend/api usually is not directly usable in the frontend.
|
|
||||||
* For that purpose some kind of value path should be defined to handle json responses in order to get only the data that is needed.
|
|
||||||
*/
|
|
||||||
self.setValueOfElement(matches[c],
|
|
||||||
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
|
||||||
);
|
|
||||||
console.log(xhr);
|
|
||||||
});
|
|
||||||
|
|
||||||
request.send();
|
remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')].push({path: path, element: matches[c]});
|
||||||
} else {
|
} else {
|
||||||
self.setValueOfElement(matches[c], self.getValueFromDataSource(values[i]));
|
self.setValueOfElement(matches[c], self.getValueFromDataSource(values[i]));
|
||||||
}
|
}
|
||||||
|
|
@ -734,8 +725,30 @@ export class Form
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const e in remoteValueUrls) {
|
||||||
|
const request = new Request(e);
|
||||||
|
request.setResultCallback(200, function(xhr) {
|
||||||
|
/**
|
||||||
|
* @todo Orange-Management/jsOMS#84
|
||||||
|
* Remote data responses need to be parsed
|
||||||
|
* The data coming from the backend/api usually is not directly usable in the frontend.
|
||||||
|
* For that purpose some kind of value path should be defined to handle json responses in order to get only the data that is needed.
|
||||||
|
*/
|
||||||
|
const remoteValueUrlsLength = remoteValueUrls[e].length;
|
||||||
|
for (let k = 0; k < remoteValueUrlsLength; ++k) {
|
||||||
|
const path = remoteValueUrls[e][k].path;
|
||||||
|
self.setValueOfElement(remoteValueUrls[e][k].element,
|
||||||
|
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
|
||||||
// insert row text data into form
|
// insert row text data into form
|
||||||
length = text.length;
|
const remoteTextUrls = {};
|
||||||
|
length = text.length;
|
||||||
for (let i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
const path = text[i].hasAttribute('data-tpl-text-path') ? text[i].getAttribute('data-tpl-text-path') : null;
|
const path = text[i].hasAttribute('data-tpl-text-path') ? text[i].getAttribute('data-tpl-text-path') : null;
|
||||||
for (let j = 0; j < selectorLength; ++j) {
|
for (let j = 0; j < selectorLength; ++j) {
|
||||||
|
|
@ -755,20 +768,11 @@ export class Form
|
||||||
? document.getElementsByTagName('base')[0].href
|
? document.getElementsByTagName('base')[0].href
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
const request = new Request(uri + text[i].getAttribute('data-tpl-text'));
|
if (remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')] === undefined) {
|
||||||
request.setResultCallback(200, function(xhr) {
|
remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')] = [];
|
||||||
/**
|
}
|
||||||
* @todo Orange-Management/jsOMS#84
|
|
||||||
* Remote data responses need to be parsed
|
|
||||||
* The data coming from the backend/api usually is not directly usable in the frontend.
|
|
||||||
* For that purpose some kind of value path should be defined to handle json responses in order to get only the data that is needed.
|
|
||||||
*/
|
|
||||||
self.setTextOfElement(matches[c],
|
|
||||||
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
request.send();
|
remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')].push({path: path, element: matches[c]});
|
||||||
} else {
|
} else {
|
||||||
self.setTextOfElement(matches[c], self.getTextFromDataSource(text[i]));
|
self.setTextOfElement(matches[c], self.getTextFromDataSource(text[i]));
|
||||||
}
|
}
|
||||||
|
|
@ -776,6 +780,27 @@ export class Form
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const e in remoteTextUrls) {
|
||||||
|
const request = new Request(e);
|
||||||
|
request.setResultCallback(200, function(xhr) {
|
||||||
|
/**
|
||||||
|
* @todo Orange-Management/jsOMS#84
|
||||||
|
* Remote data responses need to be parsed
|
||||||
|
* The data coming from the backend/api usually is not directly usable in the frontend.
|
||||||
|
* For that purpose some kind of value path should be defined to handle json responses in order to get only the data that is needed.
|
||||||
|
*/
|
||||||
|
const remoteTextUrlsLength = remoteTextUrls[e].length;
|
||||||
|
for (let k = 0; k < remoteTextUrlsLength; ++k) {
|
||||||
|
const path = remoteTextUrls[e][k].path;
|
||||||
|
self.setTextOfElement(remoteTextUrls[e][k].element,
|
||||||
|
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < selectorLength; ++i) {
|
for (let i = 0; i < selectorLength; ++i) {
|
||||||
newEle[i].firstElementChild.setAttribute('data-marker', 'tpl');
|
newEle[i].firstElementChild.setAttribute('data-marker', 'tpl');
|
||||||
parents[i].parentNode.insertBefore(newEle[i].firstElementChild, parents[i]);
|
parents[i].parentNode.insertBefore(newEle[i].firstElementChild, parents[i]);
|
||||||
|
|
@ -849,21 +874,23 @@ export class Form
|
||||||
|
|
||||||
save.addEventListener('click', function () {
|
save.addEventListener('click', function () {
|
||||||
const formElement = document.getElementById(id);
|
const formElement = document.getElementById(id);
|
||||||
const parentsTpl = [];
|
const parentsTpl = {};
|
||||||
const parentsContent = [];
|
const parentsContent = {};
|
||||||
const selectors = formElement.getAttribute('data-ui-element').split(','),
|
const selectors = formElement.getAttribute('data-ui-element').split(','),
|
||||||
selectorLength = selectors.length;
|
selectorLength = selectors.length;
|
||||||
|
|
||||||
let values = [];
|
let values = [];
|
||||||
let text = [];
|
let text = [];
|
||||||
|
|
||||||
|
// find all values, texts and parents for every selector
|
||||||
for (let i = 0; i < selectorLength; ++i) {
|
for (let i = 0; i < selectorLength; ++i) {
|
||||||
// todo: similar logic is in updatable Inline and probably in External... pull out?
|
// todo: similar logic is in updatable Inline and probably in External... pull out?
|
||||||
// this handles selectors such as 'ancestor > child/or/sibling' and many more
|
// this handles selectors such as 'ancestor > child/or/sibling' and many more
|
||||||
let selector = selectors[i].trim(' ').split(' ');
|
let selector = selectors[i].trim(' ').split(' ');
|
||||||
let closest = selector[0].trim();
|
let closest = selector[0].trim();
|
||||||
|
|
||||||
// template elements
|
// template elements (= elements which just got added due to the update/edit button, here the new data is stored)
|
||||||
|
// @todo i don't really remember how this works and why this was needed. Try to understand it and write a comment afterwards
|
||||||
let subSelector = '';
|
let subSelector = '';
|
||||||
if (selector.length !== 0) {
|
if (selector.length !== 0) {
|
||||||
selector.shift();
|
selector.shift();
|
||||||
|
|
@ -872,9 +899,11 @@ export class Form
|
||||||
closest += '[data-marker=tpl]';
|
closest += '[data-marker=tpl]';
|
||||||
}
|
}
|
||||||
|
|
||||||
parentsTpl.push(
|
const parentTplName = selector.length === 0 ? closest : closest + subSelector;
|
||||||
selector.length === 0 ? this.closest(closest) : this.closest(closest).querySelector(subSelector)
|
if (!parentsTpl.hasOwnProperty(parentTplName)) {
|
||||||
);
|
parentsTpl[parentTplName] = selector.length === 0 ? this.closest(closest) : this.closest(closest).querySelector(subSelector);
|
||||||
|
/* @todo: parentNode because of media edit. maybe I need a data-ui-parent element? */
|
||||||
|
}
|
||||||
|
|
||||||
// content elements
|
// content elements
|
||||||
selector = selectors[i].trim(' ').split(' ');
|
selector = selectors[i].trim(' ').split(' ');
|
||||||
|
|
@ -887,28 +916,40 @@ export class Form
|
||||||
closest += ':not([data-marker=tpl])';
|
closest += ':not([data-marker=tpl])';
|
||||||
}
|
}
|
||||||
|
|
||||||
parentsContent.push(
|
const parentContentName = selector.length === 0 ? closest : closest + subSelector;
|
||||||
selector.length === 0 ? this.closest(closest) : this.closest(closest).querySelector(subSelector).parentNode
|
if (!parentsContent.hasOwnProperty(parentContentName)) {
|
||||||
/* parentNode because of media edit. maybe I need a data-ui-parent element? */
|
parentsContent[parentContentName] = selector.length === 0 ? this.closest(closest) : this.closest(closest).querySelector(subSelector).parentNode;
|
||||||
);
|
/* @todo: parentNode because of media edit. maybe I need a data-ui-parent element? */
|
||||||
|
}
|
||||||
|
|
||||||
values = values.concat(
|
values = values.concat(
|
||||||
parentsTpl[i].hasAttribute('data-tpl-value') ? parentsTpl[i] : Array.prototype.slice.call(parentsTpl[i].querySelectorAll('[data-tpl-value]'))
|
parentsTpl[parentTplName].hasAttribute('data-tpl-value') ? parentsTpl[parentTplName] : Array.prototype.slice.call(parentsTpl[parentTplName].querySelectorAll('[data-tpl-value]'))
|
||||||
);
|
);
|
||||||
text = text.concat(
|
text = text.concat(
|
||||||
parentsTpl[i].hasAttribute('data-tpl-text') ? parentsTpl[i] : Array.prototype.slice.call(parentsTpl[i].querySelectorAll('[data-tpl-text]'))
|
parentsContent[parentContentName].hasAttribute('data-tpl-text') ? parentsContent[parentContentName] : Array.prototype.slice.call(parentsContent[parentContentName].querySelectorAll('[data-tpl-text]'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
values = values.filter(function(value, index, self) { return self.indexOf(value) === index; });
|
||||||
|
text = text.filter(function(value, index, self) { return self.indexOf(value) === index; });
|
||||||
|
|
||||||
// overwrite old values data in ui
|
// overwrite old values data in ui
|
||||||
length = values.length;
|
const remoteValueUrls = {};
|
||||||
for (let i = 0; i < length; ++i) {
|
const changedValueNodes = []; // prevent same node touching
|
||||||
const path = values[i].hasAttribute('data-tpl-value-path') ? values[i].getAttribute('data-tpl-value-path') : null;
|
length = values.length;
|
||||||
for (let j = 0; j < selectorLength; ++j) {
|
for (let parent in parentsTpl) { // loop every selector which has elements to change
|
||||||
const matches = parentsContent[j].querySelectorAll('[data-tpl-value="' + values[i].getAttribute('data-tpl-value') + '"');
|
for (let i = 0; i < length; ++i) { // loop every value
|
||||||
|
const matches = parentsTpl[parent].querySelectorAll('[data-tpl-value="' + values[i].getAttribute('data-tpl-value') + '"');
|
||||||
|
|
||||||
const matchLength = matches.length;
|
const matchLength = matches.length;
|
||||||
for (let c = 0; c < matchLength; ++c) {
|
for (let c = 0; c < matchLength; ++c) { // loop every found element in the selector to change
|
||||||
|
if (changedValueNodes.includes(matches[c])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
changedValueNodes.push(matches[c]);
|
||||||
|
const path = matches[c].hasAttribute('data-tpl-value-path') ? matches[c].getAttribute('data-tpl-value-path') : null;
|
||||||
|
|
||||||
if (values[i].getAttribute('data-tpl-value').startsWith('http')
|
if (values[i].getAttribute('data-tpl-value').startsWith('http')
|
||||||
|| values[i].getAttribute('data-tpl-value').startsWith('{')
|
|| values[i].getAttribute('data-tpl-value').startsWith('{')
|
||||||
) {
|
) {
|
||||||
|
|
@ -916,20 +957,11 @@ export class Form
|
||||||
? document.getElementsByTagName('base')[0].href
|
? document.getElementsByTagName('base')[0].href
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
const request = new Request(uri + values[i].getAttribute('data-tpl-value'));
|
if (remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')] === undefined) {
|
||||||
request.setResultCallback(200, function(xhr) {
|
remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')] = [];
|
||||||
/**
|
}
|
||||||
* @todo Orange-Management/jsOMS#84
|
|
||||||
* Remote data responses need to be parsed
|
|
||||||
* The data coming from the backend/api usually is not directly usable in the frontend.
|
|
||||||
* For that purpose some kind of value path should be defined to handle json responses in order to get only the data that is needed.
|
|
||||||
*/
|
|
||||||
self.setValueOfElement(matches[c],
|
|
||||||
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
request.send();
|
remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')].push({path: path, element: matches[c]});
|
||||||
} else {
|
} else {
|
||||||
self.setValueOfElement(matches[c], self.getValueFromDataSource(values[i]));
|
self.setValueOfElement(matches[c], self.getValueFromDataSource(values[i]));
|
||||||
}
|
}
|
||||||
|
|
@ -938,35 +970,34 @@ export class Form
|
||||||
}
|
}
|
||||||
|
|
||||||
// overwrite old text data in ui
|
// overwrite old text data in ui
|
||||||
length = text.length;
|
const remoteTextUrls = {};
|
||||||
for (let i = 0; i < length; ++i) {
|
const changedTextNodes = [];
|
||||||
const path = text[i].hasAttribute('data-tpl-text-path') ? text[i].getAttribute('data-tpl-text-path') : null;
|
length = text.length;
|
||||||
for (let j = 0; j < selectorLength; ++j) {
|
for (let parent in parentsContent) {
|
||||||
const matches = parentsContent[j].querySelectorAll('[data-tpl-text="' + text[i].getAttribute('data-tpl-text') + '"');
|
for (let i = 0; i < length; ++i) {
|
||||||
|
const matches = parentsContent[parent].querySelectorAll('[data-tpl-text="' + text[i].getAttribute('data-tpl-text') + '"');
|
||||||
|
|
||||||
const matchLength = matches.length;
|
const matchLength = matches.length;
|
||||||
for (let c = 0; c < matchLength; ++c) {
|
for (let c = 0; c < matchLength; ++c) {
|
||||||
|
if (changedTextNodes.includes(matches[c])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
changedTextNodes.push(matches[c]);
|
||||||
|
|
||||||
|
const path = matches[c].hasAttribute('data-tpl-text-path') ? matches[c].getAttribute('data-tpl-text-path') : null;
|
||||||
if (text[i].getAttribute('data-tpl-text').startsWith('http')
|
if (text[i].getAttribute('data-tpl-text').startsWith('http')
|
||||||
|| text[i].getAttribute('data-tpl-text').startsWith('{')
|
|| text[i].getAttribute('data-tpl-text').startsWith('{')
|
||||||
) {
|
) {
|
||||||
const uri = values[i].getAttribute('data-tpl-text').startsWith('/')
|
const uri = text[i].getAttribute('data-tpl-text').startsWith('/')
|
||||||
? document.getElementsByTagName('base')[0].href
|
? document.getElementsByTagName('base')[0].href
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
const request = new Request(uri + text[i].getAttribute('data-tpl-text'));
|
if (remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')] === undefined) {
|
||||||
request.setResultCallback(200, function(xhr) {
|
remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')] = [];
|
||||||
/**
|
}
|
||||||
* @todo Orange-Management/jsOMS#84
|
|
||||||
* Remote data responses need to be parsed
|
|
||||||
* The data coming from the backend/api usually is not directly usable in the frontend.
|
|
||||||
* For that purpose some kind of value path should be defined to handle json responses in order to get only the data that is needed.
|
|
||||||
*/
|
|
||||||
self.setTextOfElement(matches[c],
|
|
||||||
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
request.send();
|
remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')].push({path: path, element: matches[c]});
|
||||||
} else {
|
} else {
|
||||||
self.setTextOfElement(matches[c], self.getTextFromDataSource(text[i]));
|
self.setTextOfElement(matches[c], self.getTextFromDataSource(text[i]));
|
||||||
}
|
}
|
||||||
|
|
@ -974,7 +1005,55 @@ export class Form
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// todo bind failure here, if failure do cancel, if success to remove edit template
|
// todo bind failure here, if failure do cancel, if success to remove edit template
|
||||||
|
self.forms[id].setSuccess(function() {
|
||||||
|
// overwrite old values from remote response
|
||||||
|
for (const e in remoteValueUrls) {
|
||||||
|
const request = new Request(e);
|
||||||
|
request.setResultCallback(200, function(xhr) {
|
||||||
|
/**
|
||||||
|
* @todo Orange-Management/jsOMS#84
|
||||||
|
* Remote data responses need to be parsed
|
||||||
|
* The data coming from the backend/api usually is not directly usable in the frontend.
|
||||||
|
* For that purpose some kind of value path should be defined to handle json responses in order to get only the data that is needed.
|
||||||
|
*/
|
||||||
|
const remoteValueUrlsLength = remoteValueUrls[e].length;
|
||||||
|
for (let k = 0; k < remoteValueUrlsLength; ++k) {
|
||||||
|
const path = remoteValueUrls[e][k].path;
|
||||||
|
self.setValueOfElement(remoteValueUrls[e][k].element,
|
||||||
|
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
// overwrite old values from remote response
|
||||||
|
for (const e in remoteTextUrls) {
|
||||||
|
const request = new Request(e);
|
||||||
|
request.setResultCallback(200, function(xhr) {
|
||||||
|
/**
|
||||||
|
* @todo Orange-Management/jsOMS#84
|
||||||
|
* Remote data responses need to be parsed
|
||||||
|
* The data coming from the backend/api usually is not directly usable in the frontend.
|
||||||
|
* For that purpose some kind of value path should be defined to handle json responses in order to get only the data that is needed.
|
||||||
|
*/
|
||||||
|
const remoteTextUrlsLength = remoteTextUrls[e].length;
|
||||||
|
for (let k = 0; k < remoteTextUrlsLength; ++k) {
|
||||||
|
const path = remoteTextUrls[e][k].path;
|
||||||
|
|
||||||
|
self.setTextOfElement(remoteTextUrls[e][k].element,
|
||||||
|
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
});
|
||||||
self.submit(self.forms[id]);
|
self.submit(self.forms[id]);
|
||||||
self.removeEditTemplate(this, id);
|
self.removeEditTemplate(this, id);
|
||||||
});
|
});
|
||||||
|
|
@ -1194,6 +1273,10 @@ export class Form
|
||||||
case 'article':
|
case 'article':
|
||||||
case 'section':
|
case 'section':
|
||||||
case 'h1':
|
case 'h1':
|
||||||
|
if (src.hasAttribute('data-tpl-text')) {
|
||||||
|
break; // prevent overwriting setTextOfElement
|
||||||
|
}
|
||||||
|
|
||||||
src.innerHTML = jsOMS.htmlspecialchars_encode(value);
|
src.innerHTML = jsOMS.htmlspecialchars_encode(value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -1208,6 +1291,8 @@ export class Form
|
||||||
case 'pre':
|
case 'pre':
|
||||||
case 'article':
|
case 'article':
|
||||||
case 'section':
|
case 'section':
|
||||||
|
src.innerHTML = value;
|
||||||
|
break;
|
||||||
case 'h1':
|
case 'h1':
|
||||||
src.innerHTML = jsOMS.htmlspecialchars_encode(value);
|
src.innerHTML = jsOMS.htmlspecialchars_encode(value);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user