mirror of
https://github.com/Karaka-Management/jsOMS.git
synced 2026-01-11 09:58:39 +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
|
||||
length = values.length;
|
||||
const remoteValueUrls = {};
|
||||
length = values.length;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
const path = values[i].hasAttribute('data-tpl-value-path') ? values[i].getAttribute('data-tpl-value-path') : null;
|
||||
for (let j = 0; j < selectorLength; ++j) {
|
||||
|
|
@ -712,21 +713,11 @@ export class Form
|
|||
? document.getElementsByTagName('base')[0].href
|
||||
: '';
|
||||
|
||||
const request = new Request(uri + values[i].getAttribute('data-tpl-value'));
|
||||
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.
|
||||
*/
|
||||
self.setValueOfElement(matches[c],
|
||||
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
||||
);
|
||||
console.log(xhr);
|
||||
});
|
||||
if (remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')] === undefined) {
|
||||
remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')] = [];
|
||||
}
|
||||
|
||||
request.send();
|
||||
remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')].push({path: path, element: matches[c]});
|
||||
} else {
|
||||
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
|
||||
length = text.length;
|
||||
const remoteTextUrls = {};
|
||||
length = text.length;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
const path = text[i].hasAttribute('data-tpl-text-path') ? text[i].getAttribute('data-tpl-text-path') : null;
|
||||
for (let j = 0; j < selectorLength; ++j) {
|
||||
|
|
@ -755,20 +768,11 @@ export class Form
|
|||
? document.getElementsByTagName('base')[0].href
|
||||
: '';
|
||||
|
||||
const request = new Request(uri + text[i].getAttribute('data-tpl-text'));
|
||||
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.
|
||||
*/
|
||||
self.setTextOfElement(matches[c],
|
||||
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
||||
);
|
||||
});
|
||||
if (remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')] === undefined) {
|
||||
remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')] = [];
|
||||
}
|
||||
|
||||
request.send();
|
||||
remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')].push({path: path, element: matches[c]});
|
||||
} else {
|
||||
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) {
|
||||
newEle[i].firstElementChild.setAttribute('data-marker', 'tpl');
|
||||
parents[i].parentNode.insertBefore(newEle[i].firstElementChild, parents[i]);
|
||||
|
|
@ -849,21 +874,23 @@ export class Form
|
|||
|
||||
save.addEventListener('click', function () {
|
||||
const formElement = document.getElementById(id);
|
||||
const parentsTpl = [];
|
||||
const parentsContent = [];
|
||||
const parentsTpl = {};
|
||||
const parentsContent = {};
|
||||
const selectors = formElement.getAttribute('data-ui-element').split(','),
|
||||
selectorLength = selectors.length;
|
||||
|
||||
let values = [];
|
||||
let text = [];
|
||||
|
||||
// find all values, texts and parents for every selector
|
||||
for (let i = 0; i < selectorLength; ++i) {
|
||||
// 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
|
||||
let selector = selectors[i].trim(' ').split(' ');
|
||||
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 = '';
|
||||
if (selector.length !== 0) {
|
||||
selector.shift();
|
||||
|
|
@ -872,9 +899,11 @@ export class Form
|
|||
closest += '[data-marker=tpl]';
|
||||
}
|
||||
|
||||
parentsTpl.push(
|
||||
selector.length === 0 ? this.closest(closest) : this.closest(closest).querySelector(subSelector)
|
||||
);
|
||||
const parentTplName = selector.length === 0 ? closest : closest + 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
|
||||
selector = selectors[i].trim(' ').split(' ');
|
||||
|
|
@ -887,28 +916,40 @@ export class Form
|
|||
closest += ':not([data-marker=tpl])';
|
||||
}
|
||||
|
||||
parentsContent.push(
|
||||
selector.length === 0 ? this.closest(closest) : this.closest(closest).querySelector(subSelector).parentNode
|
||||
/* parentNode because of media edit. maybe I need a data-ui-parent element? */
|
||||
);
|
||||
const parentContentName = selector.length === 0 ? closest : closest + subSelector;
|
||||
if (!parentsContent.hasOwnProperty(parentContentName)) {
|
||||
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(
|
||||
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(
|
||||
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
|
||||
length = values.length;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
const path = values[i].hasAttribute('data-tpl-value-path') ? values[i].getAttribute('data-tpl-value-path') : null;
|
||||
for (let j = 0; j < selectorLength; ++j) {
|
||||
const matches = parentsContent[j].querySelectorAll('[data-tpl-value="' + values[i].getAttribute('data-tpl-value') + '"');
|
||||
const remoteValueUrls = {};
|
||||
const changedValueNodes = []; // prevent same node touching
|
||||
length = values.length;
|
||||
for (let parent in parentsTpl) { // loop every selector which has elements to change
|
||||
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;
|
||||
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')
|
||||
|| values[i].getAttribute('data-tpl-value').startsWith('{')
|
||||
) {
|
||||
|
|
@ -916,20 +957,11 @@ export class Form
|
|||
? document.getElementsByTagName('base')[0].href
|
||||
: '';
|
||||
|
||||
const request = new Request(uri + values[i].getAttribute('data-tpl-value'));
|
||||
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.
|
||||
*/
|
||||
self.setValueOfElement(matches[c],
|
||||
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
||||
);
|
||||
});
|
||||
if (remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')] === undefined) {
|
||||
remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')] = [];
|
||||
}
|
||||
|
||||
request.send();
|
||||
remoteValueUrls[uri + values[i].getAttribute('data-tpl-value')].push({path: path, element: matches[c]});
|
||||
} else {
|
||||
self.setValueOfElement(matches[c], self.getValueFromDataSource(values[i]));
|
||||
}
|
||||
|
|
@ -938,35 +970,34 @@ export class Form
|
|||
}
|
||||
|
||||
// overwrite old text data in ui
|
||||
length = text.length;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
const path = text[i].hasAttribute('data-tpl-text-path') ? text[i].getAttribute('data-tpl-text-path') : null;
|
||||
for (let j = 0; j < selectorLength; ++j) {
|
||||
const matches = parentsContent[j].querySelectorAll('[data-tpl-text="' + text[i].getAttribute('data-tpl-text') + '"');
|
||||
const remoteTextUrls = {};
|
||||
const changedTextNodes = [];
|
||||
length = text.length;
|
||||
for (let parent in parentsContent) {
|
||||
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;
|
||||
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')
|
||||
|| 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
|
||||
: '';
|
||||
|
||||
const request = new Request(uri + text[i].getAttribute('data-tpl-text'));
|
||||
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.
|
||||
*/
|
||||
self.setTextOfElement(matches[c],
|
||||
path !== null ? jsOMS.getArray(path, JSON.parse(xhr.response)) : xhr.response
|
||||
);
|
||||
});
|
||||
if (remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')] === undefined) {
|
||||
remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')] = [];
|
||||
}
|
||||
|
||||
request.send();
|
||||
remoteTextUrls[uri + text[i].getAttribute('data-tpl-value')].push({path: path, element: matches[c]});
|
||||
} else {
|
||||
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
|
||||
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.removeEditTemplate(this, id);
|
||||
});
|
||||
|
|
@ -1194,6 +1273,10 @@ export class Form
|
|||
case 'article':
|
||||
case 'section':
|
||||
case 'h1':
|
||||
if (src.hasAttribute('data-tpl-text')) {
|
||||
break; // prevent overwriting setTextOfElement
|
||||
}
|
||||
|
||||
src.innerHTML = jsOMS.htmlspecialchars_encode(value);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1208,6 +1291,8 @@ export class Form
|
|||
case 'pre':
|
||||
case 'article':
|
||||
case 'section':
|
||||
src.innerHTML = value;
|
||||
break;
|
||||
case 'h1':
|
||||
src.innerHTML = jsOMS.htmlspecialchars_encode(value);
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user