Merge branch 'develop'
Some checks failed
CI / general_module_workflow_js (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled

This commit is contained in:
Dennis Eichhorn 2025-04-27 07:50:45 +00:00
commit 30433a0485
137 changed files with 855 additions and 581 deletions

0
.gitattributes vendored Executable file → Normal file
View File

0
.github/workflows/codeql-analysis.yml vendored Executable file → Normal file
View File

2
.github/workflows/greetings.yml vendored Executable file → Normal file
View File

@ -9,5 +9,5 @@ jobs:
- uses: actions/first-interaction@v1 - uses: actions/first-interaction@v1
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thank you for createing this issue. We will check it as soon as possible.' issue-message: 'Thank you for creating this issue. We will check it as soon as possible.'
pr-message: 'Thank you for your pull request. We will check it as soon as possible.' pr-message: 'Thank you for your pull request. We will check it as soon as possible.'

0
.github/workflows/main.yml vendored Executable file → Normal file
View File

0
.gitignore vendored Executable file → Normal file
View File

0
3D/3DViewer.js Executable file → Normal file
View File

0
3D/Loader/DdsLoader.js Executable file → Normal file
View File

0
3D/Loader/MtlLoader.js Executable file → Normal file
View File

2
3D/Loader/ObjLoader.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Form manager class. * Form manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

0
3D/Loader/StlLoader.js Executable file → Normal file
View File

2
Account/Account.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Account. * Account.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Account/AccountManager.js Executable file → Normal file
View File

@ -6,7 +6,7 @@
* Account Manager. * Account Manager.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Account/AccountType.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Account type. * Account type.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Animation/Animation.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Particle class. * Particle class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Animation/Canvas/Particle.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Particle class. * Particle class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Animation/Canvas/ParticleAnimation.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Particle animation class. * Particle animation class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Asset/AssetManager.js Executable file → Normal file
View File

@ -4,7 +4,7 @@ import { jsOMS } from '../Utils/oLib.js';
* Asset manager. * Asset manager.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Auth/Auth.js Executable file → Normal file
View File

@ -10,7 +10,7 @@ import { RequestType } from '../Message/Request/RequestType.js';
* Auth class. * Auth class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

34
Autoloader.js Executable file → Normal file
View File

@ -3,13 +3,13 @@ import { AssetManager } from './Asset/AssetManager.js';
/** /**
* Autoloader. * Autoloader.
* *
* The autoloader is responsible for defining namespaces and dynamically loading javascript * The autoloader is responsible for defining namespaces and dynamically loading js
* files that are not yet included. The intention is to provide a similar functionality as * files that are not yet included. The intention is to provide a similar functionality as
* include, import etc. Contrary to it's name the autoloader is not able to truly autoload * include, import etc. Contrary to it's name the autoloader is not able to truly autoload
* referenced classes. * referenced classes.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
@ -35,27 +35,33 @@ Autoloader.assetLoader = new AssetManager();
*/ */
Autoloader.defineNamespace = function (namespace) Autoloader.defineNamespace = function (namespace)
{ {
if (Autoloader.namespaced.indexOf(namespace) === -1) { if (Autoloader.namespaced.indexOf(namespace) !== -1) {
const paths = namespace.split('.'); return;
paths.splice(0, 1); }
const length = paths.length; const paths = namespace.split('.');
let current = window.omsApp; paths.splice(0, 1);
for (let i = 0; i < length; ++i) { const length = paths.length;
if (typeof current[paths[i]] === 'undefined') { let current = window.omsApp;
current[paths[i]] = {};
}
current = current[paths[i]]; if (typeof current === 'undefined') {
return;
}
for (let i = 0; i < length; ++i) {
if (typeof current[paths[i]] === 'undefined') {
current[paths[i]] = {};
} }
Autoloader.namespaced.push(namespace); current = current[paths[i]];
} }
Autoloader.namespaced.push(namespace);
}; };
/** /**
* Collect all loaded javascript files * Collect all loaded JS files
* *
* @return {void} * @return {void}
* *

2
Config/Options.js Executable file → Normal file
View File

@ -5,7 +5,7 @@
* without redefining the same behaviour multiple times. * without redefining the same behaviour multiple times.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

0
DataStorage/CacheManager.js Executable file → Normal file
View File

2
DataStorage/LocalStorage.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* LocalStorage class. * LocalStorage class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

0
DataStorage/StorageManager.js Executable file → Normal file
View File

2
Event/EventManager.js Executable file → Normal file
View File

@ -6,7 +6,7 @@ import { Logger } from '../Log/Logger.js';
* Used for pooling requests. * Used for pooling requests.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

11
LICENSE.txt Executable file → Normal file
View File

@ -1,5 +1,6 @@
The OMS License The OMS License
Version 2.0
Version 2.2
1. Definitions 1. Definitions
@ -15,7 +16,7 @@ Version 2.0
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work.
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
@ -25,7 +26,7 @@ Version 2.0
2. Grant of Copyright License 2. Grant of Copyright License
Subject to the terms and conditions of this License, each Contributor grants to You after purchase a perpetual, worldwide, non-exclusive, irrevocable copyright license to prepare Derivative Works of, publicly display, publicly perform the Work and such Derivative Works in Source or Object form. You are not allowed to sublicense, reproduce, or distribute the Work and such Derivative Works in Source or Object form. Subject to the terms and conditions of this License, each Contributor grants to You after purchase a temporary, worldwide, non-exclusive copyright license to publicly display or publicly perform the Work in Source or Object form. You are not allowed to sublicense, reproduce, or distribute the Work and such Derivative Works in Source or Object form.
3. Redistribution 3. Redistribution
@ -46,7 +47,3 @@ Unless required by applicable law or agreed to in writing, Licensor provides the
7. Limitation of Liability 7. Limitation of Liability
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
8. Future Changes
The Licensor may change the License for future versions as he sees fit.

2
Log/LogLevel.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Log Level enum. * Log Level enum.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Log/Logger.js Executable file → Normal file
View File

@ -6,7 +6,7 @@ import { SystemUtils } from '../System/SystemUtils.js';
* Logger class. * Logger class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

3
Math/MathProcessor.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Math processor. * Math processor.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
@ -126,4 +126,3 @@ export class MathProcessor
return output; return output;
}; };
}; };

0
Media/Audio/UISound.js Executable file → Normal file
View File

0
Media/README.md Executable file → Normal file
View File

0
Media/Video/CameraRecognition.js Executable file → Normal file
View File

7
Message/Notification/App/AppNotification.js Executable file → Normal file
View File

@ -7,7 +7,7 @@ import { NotificationLevel } from '../NotificationLevel.js';
* App notification. * App notification.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
@ -108,7 +108,10 @@ export class AppNotification
const logs = document.getElementsByClassName('log-msg'); const logs = document.getElementsByClassName('log-msg');
const lastElementAdded = logs[logs.length - 1]; const lastElementAdded = logs[logs.length - 1];
window.navigator.vibrate(msg.vibrate ? 200 : 0);
if (typeof window.navigator.vibrate !== 'undefined') {
window.navigator.vibrate(msg.vibrate ? 200 : 0);
}
if (msg.isSticky) { if (msg.isSticky) {
return; return;

2
Message/Notification/Browser/BrowserNotification.js Executable file → Normal file
View File

@ -6,7 +6,7 @@
* Browser notification. * Browser notification.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Message/Notification/NotificationLevel.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Notification data enum. * Notification data enum.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Message/Notification/NotificationManager.js Executable file → Normal file
View File

@ -6,7 +6,7 @@ import { NotificationType } from '../../Message/Notification/NotificationType
* Notification manager. * Notification manager.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Message/Notification/NotificationMessage.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* App notification message. * App notification message.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Message/Notification/NotificationType.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Notification data enum. * Notification data enum.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

28
Message/Request/Request.js Executable file → Normal file
View File

@ -7,7 +7,7 @@ import { RequestType } from './RequestType.js';
* Request class. * Request class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
* *
@ -239,6 +239,11 @@ export class Request
this.data = data; this.data = data;
}; };
addData(name, data)
{
this.data[name] = data;
};
/** /**
* Get request data. * Get request data.
* *
@ -316,24 +321,17 @@ export class Request
// @question Consider to change to fetch // @question Consider to change to fetch
if (this.xhr.readyState !== 1) { if (this.xhr.readyState !== 1) {
if (this.type === RequestType.FORM_DATA) { let url = this.uri;
// GET request doesn't allow body/payload. Therefor we have to put the data into the uri if (this.method === RequestMethod.GET) {
if (this.method === RequestMethod.GET) { for (const pair of Object.entries(this.data)) {
let url = this.uri; url += '&' + pair[0] + '=' + pair[1];
for (const pair of this.data.entries()) {
url += '&' + pair[0] + '=' + pair[1];
}
this.xhr.open(this.method, UriFactory.build(url));
} else {
this.xhr.open(this.method, UriFactory.build(this.uri));
} }
} else { } else {
console.log(UriFactory.build(this.uri)); url = this.uri;
this.xhr.open(this.method, UriFactory.build(this.uri));
} }
this.xhr.open(this.method, UriFactory.build(url));
for (const p in this.requestHeader) { for (const p in this.requestHeader) {
if (Object.prototype.hasOwnProperty.call(this.requestHeader, p) && this.requestHeader[p] !== '') { if (Object.prototype.hasOwnProperty.call(this.requestHeader, p) && this.requestHeader[p] !== '') {
if (this.requestHeader[p] !== 'multipart/form-data') { if (this.requestHeader[p] !== 'multipart/form-data') {

2
Message/Request/RequestMethod.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Http request method. * Http request method.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Message/Request/RequestType.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Request type enum. * Request type enum.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Message/Response/Response.js Executable file → Normal file
View File

@ -4,7 +4,7 @@
* Used for auto handling different responses. * Used for auto handling different responses.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

6
Message/Response/ResponseManager.js Executable file → Normal file
View File

@ -1,4 +1,4 @@
import { jsOMS } from '../../Utils/oLib.js'; import { Logger } from '../../Log/Logger.js';
/** /**
* @typedef {import('../Request/Request.js').Request} Request * @typedef {import('../Request/Request.js').Request} Request
*/ */
@ -9,7 +9,7 @@ import { jsOMS } from '../../Utils/oLib.js';
* Used for auto handling different responses. * Used for auto handling different responses.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
@ -72,7 +72,7 @@ export class ResponseManager
} else if (typeof this.messages[key] !== 'undefined') { } else if (typeof this.messages[key] !== 'undefined') {
this.messages[key].null(data); this.messages[key].null(data);
} else { } else {
jsOMS.Log.Logger.instance.warning('Undefined type: ' + key); Logger.instance.warning('Undefined type: ' + key);
} }
}; };
}; };

4
Message/Response/ResponseType.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Response type enum. * Response type enum.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
@ -13,4 +13,4 @@ export const ResponseType = Object.freeze({
BLOB: 'blob', BLOB: 'blob',
ARRAYBUFFER: 'arraybuffer', ARRAYBUFFER: 'arraybuffer',
DEFAULT: '' DEFAULT: ''
}); });

View File

@ -21,5 +21,7 @@ export function domAddElement (action, callback, id)
e.appendChild.removeChild(i); e.appendChild.removeChild(i);
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Dom/Click.js Executable file → Normal file
View File

@ -25,5 +25,7 @@ export function domClickAction (action, callback, id)
i.click(); i.click();
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Dom/Datalist/Append.js Executable file → Normal file
View File

@ -22,5 +22,7 @@ export function datalistAppend (action, callback)
datalist.appendChild(option); datalist.appendChild(option);
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Dom/Datalist/Clear.js Executable file → Normal file
View File

@ -16,5 +16,7 @@ export function datalistClear (action, callback)
e.removeChild(e.firstChild); e.removeChild(e.firstChild);
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Dom/Focus.js Executable file → Normal file
View File

@ -18,5 +18,7 @@ export function focusAction (action, callback)
focus.focus(); focus.focus();
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Dom/FormSubmit.js Executable file → Normal file
View File

@ -29,5 +29,7 @@ export function formSubmitAction (action, callback, id)
formManager.submit(formManager.get(i.id)); formManager.submit(formManager.get(i.id));
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

0
Model/Action/Dom/GetValue.js Executable file → Normal file
View File

4
Model/Action/Dom/Hide.js Executable file → Normal file
View File

@ -20,5 +20,7 @@ export function hideAction (action, callback)
/** global: jsOMS */ /** global: jsOMS */
jsOMS.addClass(hide, 'vh'); jsOMS.addClass(hide, 'vh');
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Dom/Popup.js Executable file → Normal file
View File

@ -81,5 +81,7 @@ export function popupButtonAction (action, callback, id)
} }
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

View File

@ -13,10 +13,16 @@ export function redirectMessage (action, callback, id)
{ {
setTimeout(function () setTimeout(function ()
{ {
const url = action.uri === '' ? '' : UriFactory.build(action.uri);
if (action.src) { if (action.src) {
document.getElementById(action.src).src = UriFactory.build(action.uri); document.getElementById(action.src).src = url;
} else { } else {
window.location = UriFactory.build(action.uri); if (url === window.location.href || url === '') {
document.location.reload();
} else {
window.location.href = url;
}
} }
}, parseInt(action.delay)); }, parseInt(action.delay));
}; };

View File

@ -1,30 +0,0 @@
import { UriFactory } from '../../../Uri/UriFactory.js';
/**
* Reload page.
*
* @param {Object} action Action data
* @param {function} callback Callback
* @param {string} id Action element
*
* @since 1.0.0
*/
export function reloadButtonAction (action, callback, id)
{
'use strict';
setTimeout(function () {
if (action.src) {
console.log(document.getElementById(action.src).hasAttribute('data-src'));
console.log(UriFactory.build(document.getElementById(action.src).getAttribute('data-src')));
document.getElementById(action.src).src = document.getElementById(action.src).hasAttribute('data-src')
? UriFactory.build(document.getElementById(action.src).getAttribute('data-src'))
: document.getElementById(action.src).src;
} else {
document.location.reload();
}
}, parseInt(action.delay));
callback();
};

4
Model/Action/Dom/Remove.js Executable file → Normal file
View File

@ -48,5 +48,7 @@ export function removeButtonAction (action, callback, id)
}, 200); }, 200);
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

View File

@ -26,5 +26,7 @@ export function domRemoveElement (action, callback, id)
e.parentElement.removeChild(e); e.parentElement.removeChild(e);
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Dom/RemoveValue.js Executable file → Normal file
View File

@ -38,5 +38,7 @@ export function domRemoveValue (action, callback, id)
} }
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

0
Model/Action/Dom/SetValue.js Executable file → Normal file
View File

4
Model/Action/Dom/Show.js Executable file → Normal file
View File

@ -21,5 +21,7 @@ export function showAction (action, callback, id)
/** global: jsOMS */ /** global: jsOMS */
jsOMS.removeClass(show, 'vh'); jsOMS.removeClass(show, 'vh');
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Dom/Table/Append.js Executable file → Normal file
View File

@ -43,5 +43,7 @@ export function tableAppend (action, callback)
} }
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Dom/Table/Clear.js Executable file → Normal file
View File

@ -16,5 +16,7 @@ export function tableClear (action, callback)
e.removeChild(e.firstChild); e.removeChild(e.firstChild);
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

View File

@ -41,5 +41,7 @@ export function ifAction (action, callback, id)
} }
} }
callback(); if (typeof callback === 'function') {
callback();
}
}; };

4
Model/Action/Event/Prevent.js Executable file → Normal file
View File

@ -16,5 +16,7 @@ export function preventEvent (action, callback, id)
jsOMS.preventAll(action.data); jsOMS.preventAll(action.data);
callback(); if (typeof callback === 'function') {
callback();
}
}; };

10
Model/Action/Message/Log.js Executable file → Normal file
View File

@ -16,11 +16,13 @@ export function logAction (action, callback, id)
window.omsApp.notifyManager.send( window.omsApp.notifyManager.send(
new NotificationMessage( new NotificationMessage(
action.data.status, action.data[0].status,
action.data.title, action.data[0].title,
action.data.message action.data[0].message
), NotificationType.APP_NOTIFICATION ), NotificationType.APP_NOTIFICATION
); );
callback(); if (typeof callback === 'function') {
callback();
}
}; };

6
Model/Action/Message/Request.js Executable file → Normal file
View File

@ -8,10 +8,14 @@ import { Request } from '../../../Message/Request/Request.js';
* *
* @since 1.0.0 * @since 1.0.0
*/ */
export function requestAction (action, callback) export function requestAction (action, callback, id)
{ {
'use strict'; 'use strict';
if (action.uri === '') {
action.uri = document.getElementById(id).href;
}
/** global: jsOMS */ /** global: jsOMS */
const request = new Request(action.uri, action.method, action.request_type); const request = new Request(action.uri, action.method, action.request_type);

0
Model/Action/Utils/DataCollector.js Executable file → Normal file
View File

0
Model/Action/Utils/Timer.js Executable file → Normal file
View File

0
Model/Action/Validate/Keypress.js Executable file → Normal file
View File

0
Model/Message/FormValidation.js Executable file → Normal file
View File

0
Model/Message/Notify.js Executable file → Normal file
View File

View File

@ -1,15 +0,0 @@
/**
* Notification type.
*
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @since 1.0.0
*/
export const EnumNotifyType = Object.freeze({
BINARY: 0,
INFO: 1,
WARNING: 2,
ERROR: 3,
FATAL: 4
});

2
Module/ModuleFactory.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Module factory. * Module factory.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
Module/ModuleManager.js Executable file → Normal file
View File

@ -3,7 +3,7 @@ import { ModuleFactory } from './ModuleFactory.js';
* Module manager. * Module manager.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

0
README.md Executable file → Normal file
View File

0
Security/Hash/Sha1.js Executable file → Normal file
View File

0
Security/Hash/Sha1b.js Executable file → Normal file
View File

0
Socket/Client/Client.js Executable file → Normal file
View File

2
System/BrowserType.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Request data enum. * Request data enum.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
System/OSType.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Request data enum. * Request data enum.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
System/SystemUtils.js Executable file → Normal file
View File

@ -5,7 +5,7 @@ import { OSType } from './OSType.js';
* System utils class. * System utils class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
UI/ActionManager.js Executable file → Normal file
View File

@ -5,7 +5,7 @@ import { Logger } from '../Log/Logger.js';
* Action manager class. * Action manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
* *

2
UI/Component/AdvancedSelect.js Executable file → Normal file
View File

@ -13,7 +13,7 @@ import { Request } from '../../Message/Request/Request.js';
* Advanced input class. * Advanced input class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
* *

113
UI/Component/CodeArea.js Normal file
View File

@ -0,0 +1,113 @@
import { jsOMS } from '../../Utils/oLib.js';
/**
* Code text area.
*
* @copyright Dennis Eichhorn
* @license OMS License 2.2
* @version 1.0.0
* @since 1.0.0
*/
export class CodeArea {
/**
* @constructor
*
* @param {string} id Form id
*
* @since 1.0.0
*/
constructor(e) {
const self = this;
this.div = e;
this.isMouseDown = false;
// LAYOUT (table 2 panels)
const table = document.createElement('table');
table.setAttribute('cellspacing', '0');
table.setAttribute('cellpadding', '0');
const tr = document.createElement('tr');
const td1 = document.createElement('td');
const td2 = document.createElement('td');
tr.appendChild(td1);
tr.appendChild(td2);
table.appendChild(tr);
this.ta = this.div.querySelector('.codeTextarea');
// TEXTAREA NUMBERS (Canvas)
const canvas = document.createElement('canvas');
canvas.width = 48;
canvas.height = 500;
this.ta.canvasLines = canvas;
td1.appendChild(canvas);
td2.appendChild(this.ta);
this.div.appendChild(table);
this.ta.addEventListener('scroll', function (e) {
self.render();
});
this.ta.addEventListener('mousedown', function (e) {
self.isMouseDown = true;
});
this.ta.addEventListener('mouseup', function (e) {
self.isMouseDown = false;
self.render();
});
this.ta.addEventListener('mousemove', function (e) {
if (self.isMouseDown) {
self.render();
}
});
};
render () {
try {
const canvas = this.ta.canvasLines;
if (canvas.height != this.ta.clientHeight) {
canvas.height = this.ta.clientHeight; // on resize
}
const ctx = canvas.getContext('2d');
const fontSize = parseInt(window.getComputedStyle(this.ta).fontSize);
const lineHeight = parseInt(window.getComputedStyle(this.ta).lineHeight);
ctx.fillStyle = window.getComputedStyle(this.div).background;
ctx.fillRect(0, 0, 42, this.ta.scrollHeight + 1);
ctx.fillStyle = window.getComputedStyle(this.div).color;
ctx.font = window.getComputedStyle(this.ta).fontSize + ' monospace';
const startIndex = Math.floor(this.ta.scrollTop / lineHeight, 0);
const endIndex = startIndex + Math.ceil(this.ta.clientHeight / lineHeight, 0);
let ph = 0;
let text = '';
for (let i = startIndex; i < endIndex; i++) {
ph = fontSize - this.ta.scrollTop + i * lineHeight;
text = '' + (1 + i);
ctx.fillText(text, 40 - text.length * fontSize / 2, ph);
}
} catch (e) {
console.log(e.message);
}
};
};
jsOMS.ready(function ()
{
'use strict';
const textareas = document.querySelectorAll('.codeArea');
const length = textareas.length;
for (let i = 0; i < length; ++i) {
const textarea = new CodeArea(textareas[i]);
textarea.render();
}
});

89
UI/Component/Form.js Executable file → Normal file
View File

@ -15,7 +15,7 @@ import { UriFactory } from '../../Uri/UriFactory.js';
* Form manager class. * Form manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
* *
@ -242,7 +242,7 @@ export class Form
? self.forms[document.getElementById(id).getAttribute('data-update-form')].getFormElement() ? self.forms[document.getElementById(id).getAttribute('data-update-form')].getFormElement()
: ( : (
document.getElementById(id).getAttribute('data-delete-form') !== null document.getElementById(id).getAttribute('data-delete-form') !== null
? self.forms[document.getElementById(id).getAttribute('data-delete-form')].getFormElement() ? self.forms[document.getElementById(id).getAttribute('data-delete-form')].getFormElement()
: null : null
) )
); );
@ -408,7 +408,7 @@ export class Form
{ {
jsOMS.preventAll(event); jsOMS.preventAll(event);
if (document.querySelector('[data-update-form="' + id + '"') === null) { if (document.querySelector('[data-update-form="' + id + '"') === null) {
this.formActionSaveInline(self, event, id, elementIndex); this.formActionSaveInline(self, event, id, elementIndex);
} else { } else {
this.formActionSaveExternal(self, event, id, elementIndex); this.formActionSaveExternal(self, event, id, elementIndex);
@ -600,7 +600,7 @@ export class Form
formActionSaveExternal (self, event, id, elementIndex) formActionSaveExternal (self, event, id, elementIndex)
{ {
const mainForm = document.querySelector('[data-update-form="' + id + '"'); const mainForm = document.querySelector('[data-update-form="' + id + '"');
const externalFormId = id; const externalFormId = id;
id = mainForm.getAttribute('id'); id = mainForm.getAttribute('id');
@ -1180,6 +1180,17 @@ export class Form
const redirect = form.getFormElement().getAttribute('data-redirect'); const redirect = form.getFormElement().getAttribute('data-redirect');
if (form.getMethod() === 'GET_REDIRECT') {
let url = form.getAction();
for (const pair of data) {
url += '&' + pair[0] + '=' + pair[1];
}
window.location.href = url;
return;
}
request.setData(data); request.setData(data);
request.setType(RequestType.FORM_DATA); // @todo consider to allow different request type request.setType(RequestType.FORM_DATA); // @todo consider to allow different request type
request.setUri(action !== null ? action : form.getAction()); request.setUri(action !== null ? action : form.getAction());
@ -1194,14 +1205,19 @@ export class Form
} }
let statusCode = null; let statusCode = null;
let responseData = null;
if (xhr.getResponseHeader('content-type').includes('application/octet-stream')) { const contentType = xhr.getResponseHeader('content-type');
const blob = new Blob([xhr.response], { type: 'application/octet-stream' });
if (contentType !== null
&& contentType.includes('application/octet-stream')
) {
responseData = new Blob([xhr.response], { type: 'application/octet-stream' });
const doc = document.createElement('a'); const doc = document.createElement('a');
doc.style = 'display: none'; doc.style = 'display: none';
document.body.appendChild(doc); document.body.appendChild(doc);
const url = window.URL.createObjectURL(blob); const url = window.URL.createObjectURL(responseData);
doc.href = url; doc.href = url;
const disposition = xhr.getResponseHeader('content-disposition'); const disposition = xhr.getResponseHeader('content-disposition');
@ -1219,9 +1235,10 @@ export class Form
doc.click(); doc.click();
window.URL.revokeObjectURL(url); window.URL.revokeObjectURL(url);
document.body.removeChild(doc); document.body.removeChild(doc);
} else if (xhr.getResponseHeader('content-type').includes('text/html')) { } else if (contentType.includes('text/html')) {
// window.location = UriFactory.build(uri); // window.location = UriFactory.build(uri);
responseData = xhr.response;
document.documentElement.innerHTML = xhr.response; document.documentElement.innerHTML = xhr.response;
/* This is not working as it reloads the page ?! /* This is not working as it reloads the page ?!
document.open(); document.open();
@ -1232,8 +1249,8 @@ export class Form
window.omsApp.reInit(); // @todo fix memory leak which most likely exists because of continuous binding without removing binds window.omsApp.reInit(); // @todo fix memory leak which most likely exists because of continuous binding without removing binds
} else { } else {
try { try {
const o = JSON.parse(xhr.response)[0]; responseData = JSON.parse(xhr.response);
const response = new Response(o); const response = new Response(responseData[0]);
let successInject = null; let successInject = null;
statusCode = parseInt(xhr.getResponseHeader('status')); statusCode = parseInt(xhr.getResponseHeader('status'));
@ -1247,9 +1264,16 @@ export class Form
if (response.get('type') !== null) { if (response.get('type') !== null) {
self.app.responseManager.run(response.get('type'), response.get(), null); self.app.responseManager.run(response.get('type'), response.get(), null);
} else if (typeof o.status !== 'undefined' && o.status !== NotificationLevel.HIDDEN) { } else if (typeof responseData[0].status !== 'undefined'
&& responseData[0].status !== NotificationLevel.HIDDEN
) {
self.app.notifyManager.send( self.app.notifyManager.send(
new NotificationMessage(o.status, o.title, o.message), NotificationType.APP_NOTIFICATION new NotificationMessage(
responseData[0].status,
responseData[0].title,
responseData[0].message
),
NotificationType.APP_NOTIFICATION
); );
} }
} catch (e) { } catch (e) {
@ -1267,33 +1291,36 @@ export class Form
'Some failure happened' 'Some failure happened'
), NotificationType.APP_NOTIFICATION ), NotificationType.APP_NOTIFICATION
); );
statusCode = 400;
} }
} }
if (redirect !== null if (redirect !== null
&& (statusCode === 200 || statusCode === null) && (statusCode === 200 || statusCode === null)
) { ) {
fetch(UriFactory.build(redirect)) const redirectUrl = UriFactory.build(redirect, responseData);
.then((response) => response.text()) fetch(redirectUrl)
.then((html) => { .then((response) => response.text())
document.documentElement.innerHTML = html; .then((html) => {
document.documentElement.innerHTML = html;
if (window.omsApp.state) { if (window.omsApp.state) {
window.omsApp.state.hasChanges = false; window.omsApp.state.hasChanges = false;
} }
history.pushState({}, null, UriFactory.build(redirect)); history.pushState({}, null, redirectUrl);
/* This is not working as it reloads the page ?! /* This is not working as it reloads the page ?!
document.open(); document.open();
document.write(html); document.write(html);
document.close(); document.close();
*/ */
// @todo fix memory leak which most likely exists because of continuous binding without removing binds // @todo fix memory leak which most likely exists because of continuous binding without removing binds
window.omsApp.reInit(); window.omsApp.reInit();
}) })
.catch((error) => { .catch((error) => {
console.warn(error); console.warn(error);
}); });
} }
}); });

View File

@ -1,139 +0,0 @@
import { Request } from '../../Message/Request/Request.js';
import { Response } from '../../Message/Response/Response.js';
import { RequestMethod } from '../../Message/Request/RequestMethod.js';
import { ResponseType } from '../../Message/Response/ResponseType.js';
/**
* Form manager class.
*
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @since 1.0.0
*/
export class Input
{
/**
* @constructor
*
* @since 1.0.0
*/
constructor ()
{
this.visObs = null;
};
/**
* Unbind input element
*
* @param {Element} input Input element
*
* @return {void}
*
* @since 1.0.0
*/
static unbind (input)
{
this.app.inputManager.getKeyboardManager().unbind(input);
/** global: changeBind */
// input.removeEventListener('change', changeBind, false);
};
/**
* Bind input element
*
* @param {Element} input Input element
*
* @return {void}
*
* @since 1.0.0
*/
static bindElement (input = null)
{
if (input === null) {
throw new Error('Input element required');
}
const type = input.type;
const removeContentButton = input.parentNode.querySelector('.close');
if (removeContentButton !== null
&& type !== 'submit' && type !== 'button') {
removeContentButton.addEventListener('click', function () {
input.value = '';
input.focus();
});
}
};
/**
* Add remote datalist options
*
* This only applies for datalists that have remote options
*
* @param {Element} input Input element
* @param {Element} datalist Datalist element
*
* @return {void}
*
* @since 1.0.0
*/
static addRemoteDatalistOptions (input, datalist)
{
this.clearDatalistOptions(datalist);
const request = new Request();
request.setData(input.value);
request.setType(ResponseType.JSON);
request.setUri(datalist.getAttribute('data-list-src'));
request.setMethod(RequestMethod.POST);
request.setRequestHeader('Content-Type', 'application/json');
request.setSuccess(function (xhr)
{
try {
const o = JSON.parse(xhr.response);
const response = new Response(o);
const responseLength = response.count();
let tempResponse = null;
for (let k = 0; k < responseLength; ++k) {
tempResponse = response.getByIndex(k);
let option = null;
const data = tempResponse.getData();
const length = data.length;
for (let i = 0; i < length; ++i) {
option = document.createElement('option');
option.value = tempResponse.value;
option.text = tempResponse.text;
datalist.appendChild(option);
}
}
} catch (exception) {
Logger.instance.error('Invalid JSON object: ' + xhr, 'FormManager');
}
});
request.send();
};
/**
* Remove all datalist options from datalist
*
* @param {Element} datalist Datalist element
*
* @return {void}
*
* @since 1.0.0
*/
static clearDatalistOptions (datalist)
{
const length = datalist.options.length;
for (let i = 0; i < length; ++i) {
datalist.remove(0);
}
};
};

View File

@ -0,0 +1,342 @@
import { jsOMS } from '../../Utils/oLib.js';
import { Request } from '../../Message/Request/Request.js';
/**
* @typedef {import('../../Event/EventManager.js').EventManager} EventManager
*/
/**
* Smart input class.
*
* @copyright Dennis Eichhorn
* @license OMS License 2.2
* @version 1.0.0
* @since 1.0.0
*/
export class SmartTextInput
{
/**
* @constructor
*
* @param {Element} e Element to bind
*
* @since 1.0.0
*/
constructor (e)
{
/** @type {string} id */
this.id = e.id;
/** @type {Element} e */
this.inputComponent = e;
this.inputField = this.inputComponent.getElementsByClassName('input-div')[0];
this.dataList = this.inputComponent.getElementsByClassName('input-datalist')[0];
this.dataListBody = this.inputComponent.getElementsByClassName('input-datalist-body')[0];
this.dataTpl = document.getElementsByClassName('input-data-tpl')[0];
this.elementContainer = this.dataTpl.hasAttribute('data-container') ? this.dataTpl.getAttribute('data-container') : '';
this.src = this.inputComponent.getAttribute('data-src');
const self = this;
this.inputField.addEventListener('focus', function (e) {
self.dataList.classList.remove('vh');
});
this.inputField.addEventListener('click', function (e) {
self.dataList.classList.remove('vh');
});
this.inputField.addEventListener('focusout', function (e) {
setTimeout(function () {
self.dataList.classList.add('vh');
self.clearDataListSelection(self);
if (self.inputField.textContent === '') {
self.inputField.setAttribute('data-value', '');
}
if (self.inputField.classList.contains('required') && self.inputField.getAttribute('data-value') === '') {
self.inputField.classList.add('invalid');
} else {
self.inputField.classList.remove('invalid');
}
const list = self.dataListBody.getElementsByTagName('div');
const length = list.length;
if (length > 0 && self.inputField.getAttribute('data-value') !== '') {
let isValid = false;
for (let i = 0; i < length; ++i) {
const textElements = list[i].hasAttribute('data-tpl-text')
? [list[i]]
: list[i].querySelectorAll('[data-tpl-text]');
if (Array.from(textElements).map(e => e.textContent).join(' ').trim() === self.inputField.textContent) {
isValid = true;
break;
}
}
if (!isValid) {
self.inputField.classList.add('invalid');
} else {
self.inputField.classList.remove('invalid');
}
}
}, 100);
});
this.inputField.addEventListener('keydown', function (e) {
if (self.dataList.classList.contains("vh")) {
self.dataList.classList.remove('vh');
}
if (e.keyCode === 13 || e.keyCode === 40) {
jsOMS.preventAll(e);
}
if (e.keyCode === 40) {
// down-key
self.selectOption(self.dataListBody.firstElementChild);
self.dataList.focus();
jsOMS.preventAll(e);
} else {
// handle change delay
self.inputTimeDelay({ id: self.id, delay: 300 }, self.changeCallback, self, e);
}
});
// @bug This never runs?!
this.dataList.addEventListener('keydown', function (e) {
jsOMS.preventAll(e);
if (e.code === 'Escape' || e.code === 'Delete' || e.code === 'Backspace') {
// handle esc, del to go back to input field
self.inputField.focus();
self.clearDataListSelection(self);
} else if (e.code === 'ArrowUp') {
// handle up-click
if (document.activeElement.previousElementSibling !== null) {
self.clearDataListSelection(self);
self.selectOption(document.activeElement.previousElementSibling);
}
} else if (e.code === 'ArrowDown') {
// handle down-click
if (document.activeElement.nextElementSibling !== null) {
self.clearDataListSelection(self);
self.selectOption(document.activeElement.nextElementSibling);
}
} else if (e.code === 'Enter' || e.code === 'Tab') {
self.clearDataListSelection(self);
self.addToResultList(self, self.elementContainer === '' ? document.activeElement : document.activeElement.closest('.' + self.elementContainer));
}
});
this.dataList.addEventListener('click', function (e) {
self.clearDataListSelection(self);
self.addToResultList(
self, self.elementContainer === ''
? e.target
: e.target.closest('.' + self.elementContainer)
);
self.dataList.classList.add('vh');
});
};
/**
* Handle remote data response result
*
* This method adds remote results to the dropdown list for selecting
*
* @param {SmartTextInput} self This reference
* @param {Object} data Response data
*
* @return {void}
*
* @since 1.0.0
*/
remoteCallback (self, data)
{
window.omsApp.logger.log(data);
data = JSON.parse(data.response)[0];
const dataLength = data.length;
// if dropdown == true
if (self.dataList.getAttribute('data-active') !== 'true') {
return;
}
if (self.inputField.textContent === '') {
self.inputField.setAttribute('data-value', '');
}
while (self.dataListBody.firstChild) {
self.dataListBody.removeChild(self.dataListBody.firstChild);
}
let matchFound = false;
for (let i = 0; i < dataLength; ++i) {
// set readable value
const newRow = self.dataTpl.content.cloneNode(true);
let fields = newRow.querySelectorAll('[data-tpl-text]');
let fieldLength = fields.length;
for (let j = 0; j < fieldLength; ++j) {
fields[j].appendChild(
document.createTextNode(
jsOMS.getArray(fields[j].getAttribute('data-tpl-text'), data[i])
)
);
}
// set internal value
fields = newRow.querySelectorAll('[data-tpl-value]');
fieldLength = fields.length;
for (let j = 0; j < fieldLength; ++j) {
fields[j].setAttribute(
'data-value',
jsOMS.getArray(fields[j].getAttribute('data-tpl-value'), data[i])
);
}
// set data cache
newRow.firstElementChild.setAttribute('data-data', JSON.stringify(data[i]));
if (!matchFound && self.inputField.textContent === newRow.firstElementChild.textContent) {
newRow.firstElementChild.classList.add('active');
self.inputField.setAttribute('data-value', newRow.firstElementChild.getAttribute('data-value'));
matchFound = true;
}
self.dataListBody.appendChild(newRow);
}
if (!matchFound && self.inputField.getAttribute('data-value') !== '') {
self.inputField.classList.add('invalid');
} else {
self.inputField.classList.remove('invalid');
}
};
/**
* Callback for input field content change
*
* @param {SmartTextInput} self This reference
*
* @return {void}
*
* @since 1.0.0
*/
changeCallback (self)
{
// if remote data
if (typeof self.src !== 'undefined' && self.src !== '') {
const request = new Request(self.src);
request.addData(self.inputField.getAttribute('data-name'), self.inputField.textContent)
request.addData('limit', self.inputField.getAttribute('data-limit'))
request.setSuccess(function (data) { self.remoteCallback(self, data); });
request.send();
}
};
/**
* Select element in dropdown (only mark it as selected)
*
* @param {Element} e Element to select in dropdown
*
* @return {void}
*
* @since 1.0.0
*/
selectOption (e)
{
e.focus();
jsOMS.addClass(e, 'active');
};
/**
* Clear all selected/marked options in dropdown
*
* @param {SmartTextInput} self This reference
*
* @return {void}
*
* @since 1.0.0
*/
clearDataListSelection (self)
{
const list = self.dataListBody.getElementsByTagName('div');
const length = list.length;
for (let i = 0; i < length; ++i) {
jsOMS.removeClass(list[i], 'active');
}
};
/**
* 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 {SmartTextInput} self This reference
* @param {Element} e Element
*
* @return {void}
*
* @since 1.0.0
*/
addToResultList (self, e) {
// @bug There is sometimes a situation when text is in the input field and you then want to switch
// to a different drop down element. When you click on that drop down element, it doesn't fill into the input text
// you then have to click it over and over until it works
// https://github.com/Karaka-Management/jsOMS/issues/142
const data = JSON.parse(e.getAttribute('data-data'));
if (self.inputField.getAttribute('data-autocomplete') === 'true') {
self.inputField.value = jsOMS.getArray(self.inputField.getAttribute('data-value'), data);
}
const value = e.hasAttribute('data-value') ? e.getAttribute('data-value') : e.querySelector('[data-value]').getAttribute('data-value');
const textElements = e.hasAttribute('data-tpl-text') ? [e] : e.querySelectorAll('[data-tpl-text]');
self.inputField.setAttribute('data-value', value);
self.inputField.textContent = Array.from(textElements).map(e => e.textContent).join(' ').trim();
self.inputField.focus();
self.dataList.classList.add('vh');
};
/**
* 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 {SmartTextInput} self This reference (passed to callback)
* @param {Object} data Data (passed to callback)
*
* @return {void}
*
* @since 1.0.0
*/
inputTimeDelay (action, callback, self, data)
{
if (SmartTextInput.timerDelay[action.id]) {
clearTimeout(SmartTextInput.timerDelay[action.id]);
delete SmartTextInput.timerDelay[action.id];
}
SmartTextInput.timerDelay[action.id] = setTimeout(function () {
delete SmartTextInput.timerDelay[action.id];
callback(self, data);
}, action.delay);
};
};
SmartTextInput.timerDelay = {};

3
UI/Component/Tab.js Executable file → Normal file
View File

@ -6,7 +6,7 @@ import { UriFactory } from '../../Uri/UriFactory.js';
* Tab manager class. * Tab manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
@ -70,6 +70,7 @@ export class Tab
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
nodes[i].addEventListener('click', function (evt) nodes[i].addEventListener('click', function (evt)
{ {
this.querySelector('label').click();
let fragmentString = this.querySelector('label').getAttribute('for'); let fragmentString = this.querySelector('label').getAttribute('for');
/* Change Tab */ /* Change Tab */

4
UI/Component/Table.js Executable file → Normal file
View File

@ -7,7 +7,7 @@ import { ResponseType } from '../../Message/Response/ResponseType.js';
* Table manager class. * Table manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
* *
@ -154,7 +154,7 @@ export class Table
/** /**
* @todo Karaka/jsOMS#90 * @todo Karaka/jsOMS#90
* Implement export * Implement export
* Either create download in javascript from this data or make round trip to server who then sends the data. * Either create download in JS from this data or make round trip to server who then sends the data.
* The export should be possible (if available) in json, csv, excel, word, pdf, ... * The export should be possible (if available) in json, csv, excel, word, pdf, ...
* If no endpoint is specified or reachable the client side should create a json or csv export. * If no endpoint is specified or reachable the client side should create a json or csv export.
*/ */

View File

@ -9,11 +9,11 @@ import { Request } from '../../Message/Request/Request.js';
* Advanced input class. * Advanced input class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
export class AdvancedInput export class TagInput
{ {
/** /**
* @constructor * @constructor
@ -149,7 +149,7 @@ export class AdvancedInput
* *
* This method adds remote results to the dropdown list for selecting * This method adds remote results to the dropdown list for selecting
* *
* @param {AdvancedInput} self This reference * @param {TagInput} self This reference
* @param {Object} data Response data * @param {Object} data Response data
* *
* @return {void} * @return {void}
@ -217,7 +217,7 @@ export class AdvancedInput
/** /**
* Callback for input field content change * Callback for input field content change
* *
* @param {AdvancedInput} self This reference * @param {TagInput} self This reference
* *
* @return {void} * @return {void}
* *
@ -257,7 +257,7 @@ export class AdvancedInput
/** /**
* Clear all selected/marked options in dropdown * Clear all selected/marked options in dropdown
* *
* @param {AdvancedInput} self This reference * @param {TagInput} self This reference
* *
* @return {void} * @return {void}
* *
@ -283,7 +283,7 @@ export class AdvancedInput
* *
* This can add the selected dropdown elements to a table, badge list etc. depending on the template structure. * This can add the selected dropdown elements to a table, badge list etc. depending on the template structure.
* *
* @param {AdvancedInput} self This reference * @param {TagInput} self This reference
* @param {Element} e Element * @param {Element} e Element
* *
* @return {void} * @return {void}
@ -379,7 +379,7 @@ export class AdvancedInput
* *
* @param {Object} action Action type * @param {Object} action Action type
* @param {function} callback Callback to be triggered * @param {function} callback Callback to be triggered
* @param {AdvancedInput} self This reference (passed to callback) * @param {TagInput} self This reference (passed to callback)
* @param {Object} data Data (passed to callback) * @param {Object} data Data (passed to callback)
* *
* @return {void} * @return {void}
@ -388,16 +388,16 @@ export class AdvancedInput
*/ */
inputTimeDelay (action, callback, self, data) inputTimeDelay (action, callback, self, data)
{ {
if (AdvancedInput.timerDelay[action.id]) { if (TagInput.timerDelay[action.id]) {
clearTimeout(AdvancedInput.timerDelay[action.id]); clearTimeout(TagInput.timerDelay[action.id]);
delete AdvancedInput.timerDelay[action.id]; delete TagInput.timerDelay[action.id];
} }
AdvancedInput.timerDelay[action.id] = setTimeout(function () { TagInput.timerDelay[action.id] = setTimeout(function () {
delete AdvancedInput.timerDelay[action.id]; delete TagInput.timerDelay[action.id];
callback(self, data); callback(self, data);
}, action.delay); }, action.delay);
}; };
}; };
AdvancedInput.timerDelay = {}; TagInput.timerDelay = {};

2
UI/DragNDrop.js Executable file → Normal file
View File

@ -3,7 +3,7 @@ import { jsOMS } from '../Utils/oLib.js';
* Drag and drop class. * Drag and drop class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

27
UI/GeneralUI.js Executable file → Normal file
View File

@ -1,7 +1,8 @@
import { jsOMS } from '../Utils/oLib.js'; import { jsOMS } from '../Utils/oLib.js';
import { UriFactory } from '../Uri/UriFactory.js'; import { UriFactory } from '../Uri/UriFactory.js';
import { AdvancedInput } from './Component/AdvancedInput.js'; import { TagInput } from './Component/TagInput.js';
import { SmartTextInput } from './Component/SmartTextInput.js';
// import { NotificationLevel } from '../Message/Notification/NotificationLevel.js'; // import { NotificationLevel } from '../Message/Notification/NotificationLevel.js';
// import { NotificationMessage } from '../Message/Notification/NotificationMessage.js'; // import { NotificationMessage } from '../Message/Notification/NotificationMessage.js';
// import { NotificationType } from '../Message/Notification/NotificationType.js'; // import { NotificationType } from '../Message/Notification/NotificationType.js';
@ -10,7 +11,7 @@ import { AdvancedInput } from './Component/AdvancedInput.js';
* UI manager for handling basic ui elements. * UI manager for handling basic ui elements.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
@ -196,7 +197,7 @@ export class GeneralUI
} }
e[i].addEventListener('load', function () { e[i].addEventListener('load', function () {
const spinner = this.parentElement.getElementsByClassName('ispinner'); const spinner = this.parentElement.getElementsByClassName('spinner');
if (spinner.length > 0) { if (spinner.length > 0) {
spinner[0].style.display = 'none'; spinner[0].style.display = 'none';
@ -256,14 +257,28 @@ export class GeneralUI
*/ */
bindInput (e = null) bindInput (e = null)
{ {
e = e !== null let l = e !== null
? [e] ? [e]
: document.getElementsByClassName('advIpt'); : document.getElementsByClassName('advIpt');
const length = e.length; let length = l.length;
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
new AdvancedInput(e[i], this.app.eventManager, this.app.uiManager.getDOMObserver()); // eslint-disable-line no-new new TagInput(l[i], this.app.eventManager, this.app.uiManager.getDOMObserver()); // eslint-disable-line no-new
}
l = e !== null
? [e]
: document.querySelectorAll('.smart-input-wrapper');
length = l.length;
for (let i = 0; i < length; ++i) {
if (!l[i].querySelector('.input-div').hasAttribute('contenteditable')) {
continue;
}
new SmartTextInput(l[i]); // eslint-disable-line no-new
} }
}; };

2
UI/Input/InputManager.js Executable file → Normal file
View File

@ -6,7 +6,7 @@ import { VoiceManager } from '../../../jsOMS/UI/Input/Voice/VoiceManager.js';
* UI manager class. * UI manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

9
UI/Input/Keyboard/KeyboardManager.js Executable file → Normal file
View File

@ -3,7 +3,7 @@ import { jsOMS } from '../../../Utils/oLib.js';
* Keyboard manager class. * Keyboard manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
@ -60,6 +60,11 @@ export class KeyboardManager
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
elements[i].addEventListener('keydown', function (event) elements[i].addEventListener('keydown', function (event)
{ {
if (self.down.includes(event.keyCode)) {
// Already fired
return;
}
self.down.push(event.keyCode); self.down.push(event.keyCode);
self.run(element, event); self.run(element, event);
}); });
@ -90,7 +95,7 @@ export class KeyboardManager
run (element, event) run (element, event)
{ {
if (typeof this.elements[element] === 'undefined') { if (typeof this.elements[element] === 'undefined') {
throw new Error('Unexpected elmenet!'); throw new Error('Unexpected element!');
} }
const actions = this.elements[element].concat(this.elements['']); const actions = this.elements[element].concat(this.elements['']);

2
UI/Input/Mouse/ClickType.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Click type. * Click type.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
UI/Input/Mouse/EventType.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Event type. * Event type.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

16
UI/Input/Mouse/MouseManager.js Executable file → Normal file
View File

@ -5,7 +5,7 @@ import { EventType } from '../../../../jsOMS/UI/Input/Mouse/EventType.js';
* Mouse manager class. * Mouse manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
@ -37,12 +37,16 @@ export class MouseManager
*/ */
add (element, type, button, callback, exact) add (element, type, button, callback, exact)
{ {
if (typeof this.elements[element] === 'undefined') { const elements = document.querySelectorAll(element);
this.elements[element] = []; const length = elements.length;
} for (let i = 0; i < length; ++i) {
if (typeof this.elements[elements[i].id] === 'undefined') {
this.elements[elements[i].id] = [];
}
this.bind(element, type); this.bind(elements[i].id, type);
this.elements[element].push({ callback: callback, type: type, button: button, exact: exact }); this.elements[elements[i].id].push({ callback: callback, type: type, button: button, exact: exact });
}
}; };
/** /**

2
UI/Input/Touch/TouchManager.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Touch manager class. * Touch manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

2
UI/Input/Voice/ReadManager.js Executable file → Normal file
View File

@ -2,7 +2,7 @@
* Form manager class. * Form manager class.
* *
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.2
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */

Some files were not shown because too many files have changed in this diff Show More