From 8ebd749437c986d08a17a2d9822b20e6f1eeddb5 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 2 Feb 2019 23:55:31 +0100 Subject: [PATCH] Implement better upload --- UI/ActionManager.js | 2 +- UI/Component/AdvancedInput.js | 71 ++++++++++++++++++++++++++++++++++- UI/Component/Form.js | 4 +- Views/FormView.js | 12 +++--- 4 files changed, 80 insertions(+), 9 deletions(-) diff --git a/UI/ActionManager.js b/UI/ActionManager.js index bf8576e..90b8841 100644 --- a/UI/ActionManager.js +++ b/UI/ActionManager.js @@ -143,7 +143,7 @@ document.getElementById(id).addEventListener(listener.listener, function (event) { if (listener.preventDefault) { - event.preventDefault(); + jsOMS.preventAll(event); } self.runAction(this.id, listener, listener.action[0], event); diff --git a/UI/Component/AdvancedInput.js b/UI/Component/AdvancedInput.js index a826cc9..a2721f4 100644 --- a/UI/Component/AdvancedInput.js +++ b/UI/Component/AdvancedInput.js @@ -20,6 +20,8 @@ /** * @constructor * + * @param {object} e Element to bind + * * @since 1.0.0 */ constructor (e) @@ -37,6 +39,10 @@ const self = this; this.inputField.addEventListener('focusout', function(e) { + // todo: this also means that clicking on any other part of the result list that it disappears befor + // the click is registered in the result list since focusout has highest priority (e.g. sort button in table). + // so far i don't know a way to check if *any* element in the result div is clicked, if I could check this + // first then I could simply say, don't make the result div inactive! if (e.relatedTarget === null || e.relatedTarget.parentElement === null || e.relatedTarget.parentElement.parentElement === null || @@ -52,6 +58,7 @@ } if (e.keyCode === 40) { + // down-key self.selectOption(self.dataListBody.firstElementChild); jsOMS.preventAll(e); } else { @@ -92,7 +99,7 @@ } }); - this.dropdownElement.addEventListener('focusout', function(e){ + this.dropdownElement.addEventListener('focusout', function(e) { self.clearDataListSelection(self); jsOMS.removeClass(self.dropdownElement, 'active'); }); @@ -108,6 +115,16 @@ }); }; + /** + * Handle remote data response result + * + * This method adds remote results to the dropdown list for selecting + * + * @param {object} self This reference + * @param {object} data Response data + * + * @since 1.0.0 + */ remoteCallback(self, data) { data = JSON.parse(data.response); @@ -148,6 +165,10 @@ self.dataListBody.appendChild(newRow); self.dataListBody.lastElementChild.addEventListener('focusout', function(e) { + if (e.relatedTarget === null) { + return; + } + let sibling = e.relatedTarget.parentNode.firstElementChild; do { if (sibling === e.relatedTarget) { @@ -160,6 +181,13 @@ } }; + /** + * Callback for input field content change + * + * @param {object} self This reference + * + * @since 1.0.0 + */ changeCallback(self) { // if remote data @@ -170,6 +198,13 @@ } }; + /** + * Select element in dropdown (only mark it as selected) + * + * @param {object} e Element to select in dropdown + * + * @since 1.0.0 + */ selectOption(e) { e.focus(); @@ -178,6 +213,13 @@ jsOMS.addClass(e, 'active'); }; + /** + * Clear all selected/marked options in dropdown + * + * @param {object} self This reference + * + * @since 1.0.0 + */ clearDataListSelection(self) { const list = self.dataListBody.getElementsByTagName('tr'), @@ -190,6 +232,15 @@ } }; + /** + * Add selected dropdown elements to some final result list + * + * This can add the selected dropdown elements to a table, badge list etc. depending on the template structure. + * + * @param {object} self This reference + * + * @since 1.0.0 + */ addToResultList(self) { if (self.inputField.getAttribute('data-autocomplete') === 'true') { self.inputField.value = document.activeElement.querySelectorAll('[data-tpl-value="' + self.inputField.getAttribute('data-value') + '"]')[0].getAttribute('data-value'); @@ -240,8 +291,26 @@ self.tagElement.appendChild(newTag); } + + if (self.inputField.getAttribute('data-emptyAfter') === 'true') { + self.inputField.value = ''; + } + + self.inputField.focus(); }; + /** + * Delay handler (e.g. delay after finishing typing) + * + * After waiting for a delay a callback can be triggered. + * + * @param {object} action Action type + * @param {function} callback Callback to be triggered + * @param {object} self This reference (passed to callback) + * @param {object} data Data (passed to callback) + * + * @since 1.0.0 + */ inputTimeDelay(action, callback, self, data) { if (jsOMS.UI.Component.AdvancedInput.timerDelay[action.id]) { diff --git a/UI/Component/Form.js b/UI/Component/Form.js index 70a73a9..dc4abee 100644 --- a/UI/Component/Form.js +++ b/UI/Component/Form.js @@ -176,12 +176,12 @@ this.app.eventManager.attach(form.getId(), function () { self.submitForm(form); - }); + }, true); // Run all injects first for (let property in injects) { if (injects.hasOwnProperty(property)) { - counter++; + ++counter; //this.app.eventManager.addGroup(form.getId(), counter); const result = injects[property](form, form.getId()); diff --git a/Views/FormView.js b/Views/FormView.js index 0959982..3f8cdad 100644 --- a/Views/FormView.js +++ b/Views/FormView.js @@ -250,7 +250,7 @@ // handle array data (e.g. table rows with same name) const id = jsOMS.Views.FormView.getElementId(elements[i]); if (data.hasOwnProperty(id)) { - if (!data[id].isArray()) { + if (data[id].constructor !== Array) { data[id] = [data[id]]; } @@ -325,15 +325,17 @@ */ static getElementId (e) { - if (typeof e.getAttribute('name') !== 'undefined') { + if (e.getAttribute('name') !== null) { return e.getAttribute('name'); - } else if (typeof e.getAttribute('id') !== 'undefined') { + } else if (e.getAttribute('id') !== null) { return e.getAttribute('id'); - } else if (typeof e.getAttribute('data-name') !== 'undefined') { + } else if (e.getAttribute('data-name') !== null) { return e.getAttribute('data-name'); - } else if (typeof e.getAttribute('type') !== 'undefined') { + } else if (e.getAttribute('type') !== null) { return e.getAttribute('type'); } + + throw Error("Invalid id"); }; /**