diff --git a/.gitattributes b/.gitattributes old mode 100755 new mode 100644 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml old mode 100755 new mode 100644 diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml old mode 100755 new mode 100644 index adb8716..75cb759 --- a/.github/workflows/greetings.yml +++ b/.github/workflows/greetings.yml @@ -9,5 +9,5 @@ jobs: - uses: actions/first-interaction@v1 with: 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.' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml old mode 100755 new mode 100644 diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 diff --git a/3D/3DViewer.js b/3D/3DViewer.js old mode 100755 new mode 100644 diff --git a/3D/Loader/DdsLoader.js b/3D/Loader/DdsLoader.js old mode 100755 new mode 100644 diff --git a/3D/Loader/MtlLoader.js b/3D/Loader/MtlLoader.js old mode 100755 new mode 100644 diff --git a/3D/Loader/ObjLoader.js b/3D/Loader/ObjLoader.js old mode 100755 new mode 100644 index 68bf610..34c36d7 --- a/3D/Loader/ObjLoader.js +++ b/3D/Loader/ObjLoader.js @@ -2,7 +2,7 @@ * Form manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/3D/Loader/StlLoader.js b/3D/Loader/StlLoader.js old mode 100755 new mode 100644 diff --git a/Account/Account.js b/Account/Account.js old mode 100755 new mode 100644 index 9d4b0c5..d3148c4 --- a/Account/Account.js +++ b/Account/Account.js @@ -2,7 +2,7 @@ * Account. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Account/AccountManager.js b/Account/AccountManager.js old mode 100755 new mode 100644 index b0b0033..bfee0b9 --- a/Account/AccountManager.js +++ b/Account/AccountManager.js @@ -6,7 +6,7 @@ * Account Manager. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Account/AccountType.js b/Account/AccountType.js old mode 100755 new mode 100644 index 56669c9..808e5b4 --- a/Account/AccountType.js +++ b/Account/AccountType.js @@ -2,7 +2,7 @@ * Account type. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Animation/Animation.js b/Animation/Animation.js old mode 100755 new mode 100644 index 0760fb1..32d107f --- a/Animation/Animation.js +++ b/Animation/Animation.js @@ -2,7 +2,7 @@ * Particle class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Animation/Canvas/Particle.js b/Animation/Canvas/Particle.js old mode 100755 new mode 100644 index 874be6e..db19569 --- a/Animation/Canvas/Particle.js +++ b/Animation/Canvas/Particle.js @@ -2,7 +2,7 @@ * Particle class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Animation/Canvas/ParticleAnimation.js b/Animation/Canvas/ParticleAnimation.js old mode 100755 new mode 100644 index 1ebd027..ce8cf62 --- a/Animation/Canvas/ParticleAnimation.js +++ b/Animation/Canvas/ParticleAnimation.js @@ -2,7 +2,7 @@ * Particle animation class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Asset/AssetManager.js b/Asset/AssetManager.js old mode 100755 new mode 100644 index 1031aca..0a26465 --- a/Asset/AssetManager.js +++ b/Asset/AssetManager.js @@ -4,7 +4,7 @@ import { jsOMS } from '../Utils/oLib.js'; * Asset manager. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Auth/Auth.js b/Auth/Auth.js old mode 100755 new mode 100644 index f90af35..c073c17 --- a/Auth/Auth.js +++ b/Auth/Auth.js @@ -10,7 +10,7 @@ import { RequestType } from '../Message/Request/RequestType.js'; * Auth class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Autoloader.js b/Autoloader.js old mode 100755 new mode 100644 index 1f1dbde..21e6e15 --- a/Autoloader.js +++ b/Autoloader.js @@ -3,13 +3,13 @@ import { AssetManager } from './Asset/AssetManager.js'; /** * 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 * include, import etc. Contrary to it's name the autoloader is not able to truly autoload * referenced classes. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -35,27 +35,33 @@ Autoloader.assetLoader = new AssetManager(); */ Autoloader.defineNamespace = function (namespace) { - if (Autoloader.namespaced.indexOf(namespace) === -1) { - const paths = namespace.split('.'); - paths.splice(0, 1); + if (Autoloader.namespaced.indexOf(namespace) !== -1) { + return; + } - const length = paths.length; - let current = window.omsApp; + const paths = namespace.split('.'); + paths.splice(0, 1); - for (let i = 0; i < length; ++i) { - if (typeof current[paths[i]] === 'undefined') { - current[paths[i]] = {}; - } + const length = paths.length; + let current = window.omsApp; - 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} * diff --git a/Config/Options.js b/Config/Options.js old mode 100755 new mode 100644 index 74c53fe..54c7dc5 --- a/Config/Options.js +++ b/Config/Options.js @@ -5,7 +5,7 @@ * without redefining the same behaviour multiple times. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/DataStorage/CacheManager.js b/DataStorage/CacheManager.js old mode 100755 new mode 100644 diff --git a/DataStorage/LocalStorage.js b/DataStorage/LocalStorage.js old mode 100755 new mode 100644 index cef6943..3bf448e --- a/DataStorage/LocalStorage.js +++ b/DataStorage/LocalStorage.js @@ -2,7 +2,7 @@ * LocalStorage class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/DataStorage/StorageManager.js b/DataStorage/StorageManager.js old mode 100755 new mode 100644 diff --git a/Event/EventManager.js b/Event/EventManager.js old mode 100755 new mode 100644 index e0574e8..60c2f9e --- a/Event/EventManager.js +++ b/Event/EventManager.js @@ -6,7 +6,7 @@ import { Logger } from '../Log/Logger.js'; * Used for pooling requests. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/LICENSE.txt b/LICENSE.txt old mode 100755 new mode 100644 index 02b1ff5..4974faf --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,5 +1,6 @@ The OMS License -Version 2.0 + +Version 2.2 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. -"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. @@ -25,7 +26,7 @@ Version 2.0 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 @@ -46,7 +47,3 @@ Unless required by applicable law or agreed to in writing, Licensor provides the 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. - -8. Future Changes - -The Licensor may change the License for future versions as he sees fit. diff --git a/Log/LogLevel.js b/Log/LogLevel.js old mode 100755 new mode 100644 index 7e9f155..aa03208 --- a/Log/LogLevel.js +++ b/Log/LogLevel.js @@ -2,7 +2,7 @@ * Log Level enum. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Log/Logger.js b/Log/Logger.js old mode 100755 new mode 100644 index 99f7b3b..8091b64 --- a/Log/Logger.js +++ b/Log/Logger.js @@ -6,7 +6,7 @@ import { SystemUtils } from '../System/SystemUtils.js'; * Logger class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Math/MathProcessor.js b/Math/MathProcessor.js old mode 100755 new mode 100644 index b9ce189..b9867d2 --- a/Math/MathProcessor.js +++ b/Math/MathProcessor.js @@ -2,7 +2,7 @@ * Math processor. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -126,4 +126,3 @@ export class MathProcessor return output; }; }; - diff --git a/Media/Audio/UISound.js b/Media/Audio/UISound.js old mode 100755 new mode 100644 diff --git a/Media/README.md b/Media/README.md old mode 100755 new mode 100644 diff --git a/Media/Video/CameraRecognition.js b/Media/Video/CameraRecognition.js old mode 100755 new mode 100644 diff --git a/Message/Notification/App/AppNotification.js b/Message/Notification/App/AppNotification.js old mode 100755 new mode 100644 index cb500e4..4424fb2 --- a/Message/Notification/App/AppNotification.js +++ b/Message/Notification/App/AppNotification.js @@ -7,7 +7,7 @@ import { NotificationLevel } from '../NotificationLevel.js'; * App notification. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -108,7 +108,10 @@ export class AppNotification const logs = document.getElementsByClassName('log-msg'); 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) { return; diff --git a/Message/Notification/Browser/BrowserNotification.js b/Message/Notification/Browser/BrowserNotification.js old mode 100755 new mode 100644 index 8d200e7..f6a6aae --- a/Message/Notification/Browser/BrowserNotification.js +++ b/Message/Notification/Browser/BrowserNotification.js @@ -6,7 +6,7 @@ * Browser notification. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Message/Notification/NotificationLevel.js b/Message/Notification/NotificationLevel.js old mode 100755 new mode 100644 index d56469c..a439a77 --- a/Message/Notification/NotificationLevel.js +++ b/Message/Notification/NotificationLevel.js @@ -2,7 +2,7 @@ * Notification data enum. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Message/Notification/NotificationManager.js b/Message/Notification/NotificationManager.js old mode 100755 new mode 100644 index c527c04..a0379d1 --- a/Message/Notification/NotificationManager.js +++ b/Message/Notification/NotificationManager.js @@ -6,7 +6,7 @@ import { NotificationType } from '../../Message/Notification/NotificationType * Notification manager. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Message/Notification/NotificationMessage.js b/Message/Notification/NotificationMessage.js old mode 100755 new mode 100644 index 8ace5ec..d5e4869 --- a/Message/Notification/NotificationMessage.js +++ b/Message/Notification/NotificationMessage.js @@ -2,7 +2,7 @@ * App notification message. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Message/Notification/NotificationType.js b/Message/Notification/NotificationType.js old mode 100755 new mode 100644 index c46f590..a9e67ff --- a/Message/Notification/NotificationType.js +++ b/Message/Notification/NotificationType.js @@ -2,7 +2,7 @@ * Notification data enum. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Message/Request/Request.js b/Message/Request/Request.js old mode 100755 new mode 100644 index c2acc84..860329b --- a/Message/Request/Request.js +++ b/Message/Request/Request.js @@ -7,7 +7,7 @@ import { RequestType } from './RequestType.js'; * Request class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 * @@ -239,6 +239,11 @@ export class Request this.data = data; }; + addData(name, data) + { + this.data[name] = data; + }; + /** * Get request data. * @@ -316,24 +321,17 @@ export class Request // @question Consider to change to fetch if (this.xhr.readyState !== 1) { - if (this.type === RequestType.FORM_DATA) { - // GET request doesn't allow body/payload. Therefor we have to put the data into the uri - if (this.method === RequestMethod.GET) { - let url = this.uri; - 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)); + let url = this.uri; + if (this.method === RequestMethod.GET) { + for (const pair of Object.entries(this.data)) { + url += '&' + pair[0] + '=' + pair[1]; } } else { - console.log(UriFactory.build(this.uri)); - - this.xhr.open(this.method, UriFactory.build(this.uri)); + url = this.uri; } + this.xhr.open(this.method, UriFactory.build(url)); + for (const p in this.requestHeader) { if (Object.prototype.hasOwnProperty.call(this.requestHeader, p) && this.requestHeader[p] !== '') { if (this.requestHeader[p] !== 'multipart/form-data') { diff --git a/Message/Request/RequestMethod.js b/Message/Request/RequestMethod.js old mode 100755 new mode 100644 index 10a59e3..20cd93b --- a/Message/Request/RequestMethod.js +++ b/Message/Request/RequestMethod.js @@ -2,7 +2,7 @@ * Http request method. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Message/Request/RequestType.js b/Message/Request/RequestType.js old mode 100755 new mode 100644 index 647979f..9a006fa --- a/Message/Request/RequestType.js +++ b/Message/Request/RequestType.js @@ -2,7 +2,7 @@ * Request type enum. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Message/Response/Response.js b/Message/Response/Response.js old mode 100755 new mode 100644 index f758d8e..229b4f0 --- a/Message/Response/Response.js +++ b/Message/Response/Response.js @@ -4,7 +4,7 @@ * Used for auto handling different responses. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Message/Response/ResponseManager.js b/Message/Response/ResponseManager.js old mode 100755 new mode 100644 index 17b49c4..2aab07f --- a/Message/Response/ResponseManager.js +++ b/Message/Response/ResponseManager.js @@ -1,4 +1,4 @@ -import { jsOMS } from '../../Utils/oLib.js'; +import { Logger } from '../../Log/Logger.js'; /** * @typedef {import('../Request/Request.js').Request} Request */ @@ -9,7 +9,7 @@ import { jsOMS } from '../../Utils/oLib.js'; * Used for auto handling different responses. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -72,7 +72,7 @@ export class ResponseManager } else if (typeof this.messages[key] !== 'undefined') { this.messages[key].null(data); } else { - jsOMS.Log.Logger.instance.warning('Undefined type: ' + key); + Logger.instance.warning('Undefined type: ' + key); } }; }; diff --git a/Message/Response/ResponseType.js b/Message/Response/ResponseType.js old mode 100755 new mode 100644 index 9c63dc3..abbd6ff --- a/Message/Response/ResponseType.js +++ b/Message/Response/ResponseType.js @@ -2,7 +2,7 @@ * Response type enum. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -13,4 +13,4 @@ export const ResponseType = Object.freeze({ BLOB: 'blob', ARRAYBUFFER: 'arraybuffer', DEFAULT: '' -}); +}); \ No newline at end of file diff --git a/Model/Action/Dom/AddDOM.js b/Model/Action/Dom/AddDOM.js index 418057f..1bad3af 100644 --- a/Model/Action/Dom/AddDOM.js +++ b/Model/Action/Dom/AddDOM.js @@ -21,5 +21,7 @@ export function domAddElement (action, callback, id) e.appendChild.removeChild(i); } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/Click.js b/Model/Action/Dom/Click.js old mode 100755 new mode 100644 index 311529d..b8ec9ed --- a/Model/Action/Dom/Click.js +++ b/Model/Action/Dom/Click.js @@ -25,5 +25,7 @@ export function domClickAction (action, callback, id) i.click(); } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/Datalist/Append.js b/Model/Action/Dom/Datalist/Append.js old mode 100755 new mode 100644 index 5f098d3..04a94be --- a/Model/Action/Dom/Datalist/Append.js +++ b/Model/Action/Dom/Datalist/Append.js @@ -22,5 +22,7 @@ export function datalistAppend (action, callback) datalist.appendChild(option); } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/Datalist/Clear.js b/Model/Action/Dom/Datalist/Clear.js old mode 100755 new mode 100644 index bd0bba2..a1fc0fa --- a/Model/Action/Dom/Datalist/Clear.js +++ b/Model/Action/Dom/Datalist/Clear.js @@ -16,5 +16,7 @@ export function datalistClear (action, callback) e.removeChild(e.firstChild); } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/Focus.js b/Model/Action/Dom/Focus.js old mode 100755 new mode 100644 index f1a5daf..f571967 --- a/Model/Action/Dom/Focus.js +++ b/Model/Action/Dom/Focus.js @@ -18,5 +18,7 @@ export function focusAction (action, callback) focus.focus(); - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/FormSubmit.js b/Model/Action/Dom/FormSubmit.js old mode 100755 new mode 100644 index 020d36a..7e687eb --- a/Model/Action/Dom/FormSubmit.js +++ b/Model/Action/Dom/FormSubmit.js @@ -29,5 +29,7 @@ export function formSubmitAction (action, callback, id) formManager.submit(formManager.get(i.id)); } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/GetValue.js b/Model/Action/Dom/GetValue.js old mode 100755 new mode 100644 diff --git a/Model/Action/Dom/Hide.js b/Model/Action/Dom/Hide.js old mode 100755 new mode 100644 index 69a948d..05de02b --- a/Model/Action/Dom/Hide.js +++ b/Model/Action/Dom/Hide.js @@ -20,5 +20,7 @@ export function hideAction (action, callback) /** global: jsOMS */ jsOMS.addClass(hide, 'vh'); - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/Popup.js b/Model/Action/Dom/Popup.js old mode 100755 new mode 100644 index 9643eb0..3aa791a --- a/Model/Action/Dom/Popup.js +++ b/Model/Action/Dom/Popup.js @@ -81,5 +81,7 @@ export function popupButtonAction (action, callback, id) } } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/Redirect.js b/Model/Action/Dom/Redirect.js index 5fc7696..5da174a 100644 --- a/Model/Action/Dom/Redirect.js +++ b/Model/Action/Dom/Redirect.js @@ -13,10 +13,16 @@ export function redirectMessage (action, callback, id) { setTimeout(function () { + const url = action.uri === '' ? '' : UriFactory.build(action.uri); + if (action.src) { - document.getElementById(action.src).src = UriFactory.build(action.uri); + document.getElementById(action.src).src = url; } else { - window.location = UriFactory.build(action.uri); + if (url === window.location.href || url === '') { + document.location.reload(); + } else { + window.location.href = url; + } } }, parseInt(action.delay)); }; diff --git a/Model/Action/Dom/Reload.js b/Model/Action/Dom/Reload.js deleted file mode 100755 index 22ef174..0000000 --- a/Model/Action/Dom/Reload.js +++ /dev/null @@ -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(); -}; diff --git a/Model/Action/Dom/Remove.js b/Model/Action/Dom/Remove.js old mode 100755 new mode 100644 index f8b92aa..185eded --- a/Model/Action/Dom/Remove.js +++ b/Model/Action/Dom/Remove.js @@ -48,5 +48,7 @@ export function removeButtonAction (action, callback, id) }, 200); } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/RemoveDOM.js b/Model/Action/Dom/RemoveDOM.js index 5c851ac..7e6838b 100644 --- a/Model/Action/Dom/RemoveDOM.js +++ b/Model/Action/Dom/RemoveDOM.js @@ -26,5 +26,7 @@ export function domRemoveElement (action, callback, id) e.parentElement.removeChild(e); } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/RemoveValue.js b/Model/Action/Dom/RemoveValue.js old mode 100755 new mode 100644 index 22b8119..3532b5d --- a/Model/Action/Dom/RemoveValue.js +++ b/Model/Action/Dom/RemoveValue.js @@ -38,5 +38,7 @@ export function domRemoveValue (action, callback, id) } } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/SetValue.js b/Model/Action/Dom/SetValue.js old mode 100755 new mode 100644 diff --git a/Model/Action/Dom/Show.js b/Model/Action/Dom/Show.js old mode 100755 new mode 100644 index 9b94e9f..c1faf25 --- a/Model/Action/Dom/Show.js +++ b/Model/Action/Dom/Show.js @@ -21,5 +21,7 @@ export function showAction (action, callback, id) /** global: jsOMS */ jsOMS.removeClass(show, 'vh'); - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/Table/Append.js b/Model/Action/Dom/Table/Append.js old mode 100755 new mode 100644 index f5dfe8d..0010b5e --- a/Model/Action/Dom/Table/Append.js +++ b/Model/Action/Dom/Table/Append.js @@ -43,5 +43,7 @@ export function tableAppend (action, callback) } } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Dom/Table/Clear.js b/Model/Action/Dom/Table/Clear.js old mode 100755 new mode 100644 index b3034ab..f25fdf7 --- a/Model/Action/Dom/Table/Clear.js +++ b/Model/Action/Dom/Table/Clear.js @@ -16,5 +16,7 @@ export function tableClear (action, callback) e.removeChild(e.firstChild); } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Event/If.js b/Model/Action/Event/If.js index 1eda2c2..2754f3a 100644 --- a/Model/Action/Event/If.js +++ b/Model/Action/Event/If.js @@ -41,5 +41,7 @@ export function ifAction (action, callback, id) } } - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Event/Prevent.js b/Model/Action/Event/Prevent.js old mode 100755 new mode 100644 index c8ab32f..cdc7368 --- a/Model/Action/Event/Prevent.js +++ b/Model/Action/Event/Prevent.js @@ -16,5 +16,7 @@ export function preventEvent (action, callback, id) jsOMS.preventAll(action.data); - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Message/Log.js b/Model/Action/Message/Log.js old mode 100755 new mode 100644 index fea4e4d..8950196 --- a/Model/Action/Message/Log.js +++ b/Model/Action/Message/Log.js @@ -16,11 +16,13 @@ export function logAction (action, callback, id) window.omsApp.notifyManager.send( new NotificationMessage( - action.data.status, - action.data.title, - action.data.message + action.data[0].status, + action.data[0].title, + action.data[0].message ), NotificationType.APP_NOTIFICATION ); - callback(); + if (typeof callback === 'function') { + callback(); + } }; diff --git a/Model/Action/Message/Request.js b/Model/Action/Message/Request.js old mode 100755 new mode 100644 index 1c0f041..9028c33 --- a/Model/Action/Message/Request.js +++ b/Model/Action/Message/Request.js @@ -8,10 +8,14 @@ import { Request } from '../../../Message/Request/Request.js'; * * @since 1.0.0 */ -export function requestAction (action, callback) +export function requestAction (action, callback, id) { 'use strict'; + if (action.uri === '') { + action.uri = document.getElementById(id).href; + } + /** global: jsOMS */ const request = new Request(action.uri, action.method, action.request_type); diff --git a/Model/Action/Utils/DataCollector.js b/Model/Action/Utils/DataCollector.js old mode 100755 new mode 100644 diff --git a/Model/Action/Utils/Timer.js b/Model/Action/Utils/Timer.js old mode 100755 new mode 100644 diff --git a/Model/Action/Validate/Keypress.js b/Model/Action/Validate/Keypress.js old mode 100755 new mode 100644 diff --git a/Model/Message/FormValidation.js b/Model/Message/FormValidation.js old mode 100755 new mode 100644 diff --git a/Model/Message/Notify.js b/Model/Message/Notify.js old mode 100755 new mode 100644 diff --git a/Model/Message/NotifyType.js b/Model/Message/NotifyType.js deleted file mode 100755 index 05321f9..0000000 --- a/Model/Message/NotifyType.js +++ /dev/null @@ -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 -}); diff --git a/Module/ModuleFactory.js b/Module/ModuleFactory.js old mode 100755 new mode 100644 index 8d26f60..df539fd --- a/Module/ModuleFactory.js +++ b/Module/ModuleFactory.js @@ -2,7 +2,7 @@ * Module factory. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Module/ModuleManager.js b/Module/ModuleManager.js old mode 100755 new mode 100644 index e08761a..43c16ff --- a/Module/ModuleManager.js +++ b/Module/ModuleManager.js @@ -3,7 +3,7 @@ import { ModuleFactory } from './ModuleFactory.js'; * Module manager. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/Security/Hash/Sha1.js b/Security/Hash/Sha1.js old mode 100755 new mode 100644 diff --git a/Security/Hash/Sha1b.js b/Security/Hash/Sha1b.js old mode 100755 new mode 100644 diff --git a/Socket/Client/Client.js b/Socket/Client/Client.js old mode 100755 new mode 100644 diff --git a/System/BrowserType.js b/System/BrowserType.js old mode 100755 new mode 100644 index 1ff726c..02d85aa --- a/System/BrowserType.js +++ b/System/BrowserType.js @@ -2,7 +2,7 @@ * Request data enum. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/System/OSType.js b/System/OSType.js old mode 100755 new mode 100644 index ab3055a..078e520 --- a/System/OSType.js +++ b/System/OSType.js @@ -2,7 +2,7 @@ * Request data enum. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/System/SystemUtils.js b/System/SystemUtils.js old mode 100755 new mode 100644 index a9470e2..7420baa --- a/System/SystemUtils.js +++ b/System/SystemUtils.js @@ -5,7 +5,7 @@ import { OSType } from './OSType.js'; * System utils class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/ActionManager.js b/UI/ActionManager.js old mode 100755 new mode 100644 index d05291a..695774c --- a/UI/ActionManager.js +++ b/UI/ActionManager.js @@ -5,7 +5,7 @@ import { Logger } from '../Log/Logger.js'; * Action manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 * diff --git a/UI/Component/AdvancedCalendar.js b/UI/Component/AdvancedCalendar.js deleted file mode 100755 index e69de29..0000000 diff --git a/UI/Component/AdvancedRange.js b/UI/Component/AdvancedRange.js deleted file mode 100755 index e69de29..0000000 diff --git a/UI/Component/AdvancedSelect.js b/UI/Component/AdvancedSelect.js old mode 100755 new mode 100644 index ce8604e..25ce78b --- a/UI/Component/AdvancedSelect.js +++ b/UI/Component/AdvancedSelect.js @@ -13,7 +13,7 @@ import { Request } from '../../Message/Request/Request.js'; * Advanced input class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 * diff --git a/UI/Component/CodeArea.js b/UI/Component/CodeArea.js new file mode 100644 index 0000000..0d70baa --- /dev/null +++ b/UI/Component/CodeArea.js @@ -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(); + } +}); diff --git a/UI/Component/Form.js b/UI/Component/Form.js old mode 100755 new mode 100644 index e225a7c..d708ab7 --- a/UI/Component/Form.js +++ b/UI/Component/Form.js @@ -15,7 +15,7 @@ import { UriFactory } from '../../Uri/UriFactory.js'; * Form manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 * @@ -242,7 +242,7 @@ export class Form ? self.forms[document.getElementById(id).getAttribute('data-update-form')].getFormElement() : ( 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 ) ); @@ -408,7 +408,7 @@ export class Form { 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); } else { this.formActionSaveExternal(self, event, id, elementIndex); @@ -600,7 +600,7 @@ export class Form formActionSaveExternal (self, event, id, elementIndex) { - const mainForm = document.querySelector('[data-update-form="' + id + '"'); + const mainForm = document.querySelector('[data-update-form="' + id + '"'); const externalFormId = id; id = mainForm.getAttribute('id'); @@ -1180,6 +1180,17 @@ export class Form 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.setType(RequestType.FORM_DATA); // @todo consider to allow different request type request.setUri(action !== null ? action : form.getAction()); @@ -1194,14 +1205,19 @@ export class Form } let statusCode = null; + let responseData = null; - if (xhr.getResponseHeader('content-type').includes('application/octet-stream')) { - const blob = new Blob([xhr.response], { type: 'application/octet-stream' }); + const contentType = xhr.getResponseHeader('content-type'); + + if (contentType !== null + && contentType.includes('application/octet-stream') + ) { + responseData = new Blob([xhr.response], { type: 'application/octet-stream' }); const doc = document.createElement('a'); doc.style = 'display: none'; document.body.appendChild(doc); - const url = window.URL.createObjectURL(blob); + const url = window.URL.createObjectURL(responseData); doc.href = url; const disposition = xhr.getResponseHeader('content-disposition'); @@ -1219,9 +1235,10 @@ export class Form doc.click(); window.URL.revokeObjectURL(url); document.body.removeChild(doc); - } else if (xhr.getResponseHeader('content-type').includes('text/html')) { + } else if (contentType.includes('text/html')) { // window.location = UriFactory.build(uri); + responseData = xhr.response; document.documentElement.innerHTML = xhr.response; /* This is not working as it reloads the page ?! 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 } else { try { - const o = JSON.parse(xhr.response)[0]; - const response = new Response(o); + responseData = JSON.parse(xhr.response); + const response = new Response(responseData[0]); let successInject = null; statusCode = parseInt(xhr.getResponseHeader('status')); @@ -1247,9 +1264,16 @@ export class Form if (response.get('type') !== 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( - 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) { @@ -1267,33 +1291,36 @@ export class Form 'Some failure happened' ), NotificationType.APP_NOTIFICATION ); + + statusCode = 400; } } if (redirect !== null && (statusCode === 200 || statusCode === null) ) { - fetch(UriFactory.build(redirect)) - .then((response) => response.text()) - .then((html) => { - document.documentElement.innerHTML = html; + const redirectUrl = UriFactory.build(redirect, responseData); + fetch(redirectUrl) + .then((response) => response.text()) + .then((html) => { + document.documentElement.innerHTML = html; - if (window.omsApp.state) { - window.omsApp.state.hasChanges = false; - } + if (window.omsApp.state) { + window.omsApp.state.hasChanges = false; + } - history.pushState({}, null, UriFactory.build(redirect)); - /* This is not working as it reloads the page ?! - document.open(); - document.write(html); - document.close(); - */ - // @todo fix memory leak which most likely exists because of continuous binding without removing binds - window.omsApp.reInit(); - }) - .catch((error) => { - console.warn(error); - }); + history.pushState({}, null, redirectUrl); + /* This is not working as it reloads the page ?! + document.open(); + document.write(html); + document.close(); + */ + // @todo fix memory leak which most likely exists because of continuous binding without removing binds + window.omsApp.reInit(); + }) + .catch((error) => { + console.warn(error); + }); } }); diff --git a/UI/Component/Input.js b/UI/Component/Input.js deleted file mode 100755 index cf684e2..0000000 --- a/UI/Component/Input.js +++ /dev/null @@ -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); - } - }; -}; diff --git a/UI/Component/SmartTextInput.js b/UI/Component/SmartTextInput.js new file mode 100644 index 0000000..5178554 --- /dev/null +++ b/UI/Component/SmartTextInput.js @@ -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 = {}; diff --git a/UI/Component/Tab.js b/UI/Component/Tab.js old mode 100755 new mode 100644 index 252522e..7670f17 --- a/UI/Component/Tab.js +++ b/UI/Component/Tab.js @@ -6,7 +6,7 @@ import { UriFactory } from '../../Uri/UriFactory.js'; * Tab manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -70,6 +70,7 @@ export class Tab for (let i = 0; i < length; ++i) { nodes[i].addEventListener('click', function (evt) { + this.querySelector('label').click(); let fragmentString = this.querySelector('label').getAttribute('for'); /* Change Tab */ diff --git a/UI/Component/Table.js b/UI/Component/Table.js old mode 100755 new mode 100644 index c176ea8..db99d37 --- a/UI/Component/Table.js +++ b/UI/Component/Table.js @@ -7,7 +7,7 @@ import { ResponseType } from '../../Message/Response/ResponseType.js'; * Table manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 * @@ -154,7 +154,7 @@ export class Table /** * @todo Karaka/jsOMS#90 * 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, ... * If no endpoint is specified or reachable the client side should create a json or csv export. */ diff --git a/UI/Component/AdvancedInput.js b/UI/Component/TagInput.js old mode 100755 new mode 100644 similarity index 95% rename from UI/Component/AdvancedInput.js rename to UI/Component/TagInput.js index b255ce3..9d61edf --- a/UI/Component/AdvancedInput.js +++ b/UI/Component/TagInput.js @@ -9,11 +9,11 @@ import { Request } from '../../Message/Request/Request.js'; * Advanced input class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ -export class AdvancedInput +export class TagInput { /** * @constructor @@ -149,7 +149,7 @@ export class AdvancedInput * * 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 * * @return {void} @@ -217,7 +217,7 @@ export class AdvancedInput /** * Callback for input field content change * - * @param {AdvancedInput} self This reference + * @param {TagInput} self This reference * * @return {void} * @@ -257,7 +257,7 @@ export class AdvancedInput /** * Clear all selected/marked options in dropdown * - * @param {AdvancedInput} self This reference + * @param {TagInput} self This reference * * @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. * - * @param {AdvancedInput} self This reference + * @param {TagInput} self This reference * @param {Element} e Element * * @return {void} @@ -379,7 +379,7 @@ export class AdvancedInput * * @param {Object} action Action type * @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) * * @return {void} @@ -388,16 +388,16 @@ export class AdvancedInput */ inputTimeDelay (action, callback, self, data) { - if (AdvancedInput.timerDelay[action.id]) { - clearTimeout(AdvancedInput.timerDelay[action.id]); - delete AdvancedInput.timerDelay[action.id]; + if (TagInput.timerDelay[action.id]) { + clearTimeout(TagInput.timerDelay[action.id]); + delete TagInput.timerDelay[action.id]; } - AdvancedInput.timerDelay[action.id] = setTimeout(function () { - delete AdvancedInput.timerDelay[action.id]; + TagInput.timerDelay[action.id] = setTimeout(function () { + delete TagInput.timerDelay[action.id]; callback(self, data); }, action.delay); }; }; -AdvancedInput.timerDelay = {}; +TagInput.timerDelay = {}; diff --git a/UI/DragNDrop.js b/UI/DragNDrop.js old mode 100755 new mode 100644 index a6a2052..07cd3b2 --- a/UI/DragNDrop.js +++ b/UI/DragNDrop.js @@ -3,7 +3,7 @@ import { jsOMS } from '../Utils/oLib.js'; * Drag and drop class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/GeneralUI.js b/UI/GeneralUI.js old mode 100755 new mode 100644 index a82c9c7..22680aa --- a/UI/GeneralUI.js +++ b/UI/GeneralUI.js @@ -1,7 +1,8 @@ import { jsOMS } from '../Utils/oLib.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 { NotificationMessage } from '../Message/Notification/NotificationMessage.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. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -196,7 +197,7 @@ export class GeneralUI } e[i].addEventListener('load', function () { - const spinner = this.parentElement.getElementsByClassName('ispinner'); + const spinner = this.parentElement.getElementsByClassName('spinner'); if (spinner.length > 0) { spinner[0].style.display = 'none'; @@ -256,14 +257,28 @@ export class GeneralUI */ bindInput (e = null) { - e = e !== null + let l = e !== null ? [e] : document.getElementsByClassName('advIpt'); - const length = e.length; + let length = l.length; 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 } }; diff --git a/UI/Input/InputManager.js b/UI/Input/InputManager.js old mode 100755 new mode 100644 index 68b0fa7..b5d647f --- a/UI/Input/InputManager.js +++ b/UI/Input/InputManager.js @@ -6,7 +6,7 @@ import { VoiceManager } from '../../../jsOMS/UI/Input/Voice/VoiceManager.js'; * UI manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/Input/Keyboard/KeyboardManager.js b/UI/Input/Keyboard/KeyboardManager.js old mode 100755 new mode 100644 index 2bfafab..3579710 --- a/UI/Input/Keyboard/KeyboardManager.js +++ b/UI/Input/Keyboard/KeyboardManager.js @@ -3,7 +3,7 @@ import { jsOMS } from '../../../Utils/oLib.js'; * Keyboard manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -60,6 +60,11 @@ export class KeyboardManager for (let i = 0; i < length; ++i) { elements[i].addEventListener('keydown', function (event) { + if (self.down.includes(event.keyCode)) { + // Already fired + return; + } + self.down.push(event.keyCode); self.run(element, event); }); @@ -90,7 +95,7 @@ export class KeyboardManager run (element, event) { if (typeof this.elements[element] === 'undefined') { - throw new Error('Unexpected elmenet!'); + throw new Error('Unexpected element!'); } const actions = this.elements[element].concat(this.elements['']); diff --git a/UI/Input/Mouse/ClickType.js b/UI/Input/Mouse/ClickType.js old mode 100755 new mode 100644 index 2af23a8..acee2fc --- a/UI/Input/Mouse/ClickType.js +++ b/UI/Input/Mouse/ClickType.js @@ -2,7 +2,7 @@ * Click type. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/Input/Mouse/EventType.js b/UI/Input/Mouse/EventType.js old mode 100755 new mode 100644 index ca2244d..18ecf71 --- a/UI/Input/Mouse/EventType.js +++ b/UI/Input/Mouse/EventType.js @@ -2,7 +2,7 @@ * Event type. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/Input/Mouse/MouseManager.js b/UI/Input/Mouse/MouseManager.js old mode 100755 new mode 100644 index 1227799..337c88b --- a/UI/Input/Mouse/MouseManager.js +++ b/UI/Input/Mouse/MouseManager.js @@ -5,7 +5,7 @@ import { EventType } from '../../../../jsOMS/UI/Input/Mouse/EventType.js'; * Mouse manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -37,12 +37,16 @@ export class MouseManager */ add (element, type, button, callback, exact) { - if (typeof this.elements[element] === 'undefined') { - this.elements[element] = []; - } + const elements = document.querySelectorAll(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.elements[element].push({ callback: callback, type: type, button: button, exact: exact }); + this.bind(elements[i].id, type); + this.elements[elements[i].id].push({ callback: callback, type: type, button: button, exact: exact }); + } }; /** diff --git a/UI/Input/Touch/TouchManager.js b/UI/Input/Touch/TouchManager.js old mode 100755 new mode 100644 index 0ddfb94..4aa898c --- a/UI/Input/Touch/TouchManager.js +++ b/UI/Input/Touch/TouchManager.js @@ -2,7 +2,7 @@ * Touch manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/Input/Voice/ReadManager.js b/UI/Input/Voice/ReadManager.js old mode 100755 new mode 100644 index 020a872..151a62c --- a/UI/Input/Voice/ReadManager.js +++ b/UI/Input/Voice/ReadManager.js @@ -2,7 +2,7 @@ * Form manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/Input/Voice/VoiceManager.js b/UI/Input/Voice/VoiceManager.js old mode 100755 new mode 100644 index c96b2da..b3d56a5 --- a/UI/Input/Voice/VoiceManager.js +++ b/UI/Input/Voice/VoiceManager.js @@ -5,7 +5,7 @@ import { Logger } from '../../../Log/Logger.js'; * Voice manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -28,7 +28,7 @@ export class VoiceManager this.recognition = null; this.speechRecognitionList = null; - if (SpeechRecognition !== null) { + if (SpeechRecognition !== null && SpeechGrammarList !== null) { this.recognition = new SpeechRecognition(); this.speechRecognitionList = new SpeechGrammarList(); } diff --git a/UI/Order.js b/UI/Order.js old mode 100755 new mode 100644 index c9022a4..56c6cec --- a/UI/Order.js +++ b/UI/Order.js @@ -3,7 +3,7 @@ import { jsOMS } from '../Utils/oLib.js'; * Manual order class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/RemoteData.js b/UI/RemoteData.js old mode 100755 new mode 100644 index d3f3549..29148ce --- a/UI/RemoteData.js +++ b/UI/RemoteData.js @@ -8,7 +8,7 @@ import { GeneralUI } from './GeneralUI.js'; * Remote data class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/UIManager.js b/UI/UIManager.js old mode 100755 new mode 100644 index ca70c7d..bb69d16 --- a/UI/UIManager.js +++ b/UI/UIManager.js @@ -12,7 +12,7 @@ import { UIStateManager } from './UIStateManager.js'; * UI manager for handling basic ui elements. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UI/UIStateManager.js b/UI/UIStateManager.js old mode 100755 new mode 100644 index 5215677..dd2c2b5 --- a/UI/UIStateManager.js +++ b/UI/UIStateManager.js @@ -2,7 +2,7 @@ * UI state manager class. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/UnhandledException.js b/UnhandledException.js old mode 100755 new mode 100644 index d0a9cff..4975610 --- a/UnhandledException.js +++ b/UnhandledException.js @@ -4,7 +4,7 @@ * This class handles all unhandled exceptions depending on the configuration. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Uri/HttpUri.js b/Uri/HttpUri.js old mode 100755 new mode 100644 index 077d01d..aac7e9b --- a/Uri/HttpUri.js +++ b/Uri/HttpUri.js @@ -5,7 +5,7 @@ import { jsOMS } from '../Utils/oLib.js'; * This class is for creating, modifying and analyzing http uris. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Uri/UriFactory.js b/Uri/UriFactory.js old mode 100755 new mode 100644 index d2c4c2b..281ed89 --- a/Uri/UriFactory.js +++ b/Uri/UriFactory.js @@ -6,7 +6,7 @@ import { FormView } from './../Views/FormView.js'; * Uri factory. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ @@ -212,11 +212,16 @@ export class UriFactory } } - let parsed = uri.replace(new RegExp('\{[\/#\?%@\.\$\!].*?\}', 'g'), function (match) { + let parsed = uri.replace(new RegExp('\{[\/#\?%@°\.\$\!].*?\}', 'g'), function (match) { match = match.substring(1, match.length - 1); - if (toMatch !== null && Object.prototype.hasOwnProperty.call(toMatch, match)) { - return toMatch[match]; + if (toMatch !== null + && (Object.prototype.hasOwnProperty.call(toMatch, match) + || match.includes('/')) + ) { + return typeof toMatch[match] === 'undefined' + ? (match.includes('/') ? jsOMS.getArray(match, toMatch) : toMatch[match]) + : toMatch[match] } else if (typeof UriFactory.uri[match] !== 'undefined') { return UriFactory.uri[match]; } else if (match.indexOf('!') === 0) { @@ -265,6 +270,20 @@ export class UriFactory return current.query(); } else if (match.indexOf('/') === 0 && match.length === 1) { return current.path; + } else if (match.indexOf('°') === 0 && match.length === 1) { + if(!navigator.geolocation) { + return; + } + + var lat = 0.0; + var lon = 0.0; + + navigator.geolocation.getCurrentPosition(position => { + lat = position.coords.latitude; + lon = position.coords.longitude; + }); + + return lat === 0.0 && lon === 0.0 ? '' : lat + ',' + lon; } else if (match.indexOf(':user') === 0) { return current.user; } else if (match.indexOf(':pass') === 0) { diff --git a/Utils/Debug.js b/Utils/Debug.js deleted file mode 100755 index 7692c0d..0000000 --- a/Utils/Debug.js +++ /dev/null @@ -1,113 +0,0 @@ -const visited = []; -const findings = {}; -const cssSelectors = {}; -const cssFiles = ['http://127.0.0.1/cssOMS/styles.css']; -const cssFilesLength = cssFiles.length; -const domain = window.location.hostname; -const pageLimit = 10; - -const cssRequest = new XMLHttpRequest(); -cssRequest.onreadystatechange = function () -{ - if (cssRequest.readyState === 4 && cssRequest.status === 200) { - const cssText = this.responseText; - const result = cssText.match(/[a-zA-Z0-9\ :>~\.\"'#,\[\]=\-\(\)\*]+{/g); - const resultLength = result.length; - - for (let i = 1; i < resultLength; ++i) { - const sel = result[i].substring(0, result[i].length - 1).trimLeft().trimRight().trimRight(); - if (!Object.prototype.hasOwnProperty.call(cssSelectors, sel)) { - cssSelectors[sel] = 0; - } - } - } -}; - -for (let i = 0; i < cssFilesLength; ++i) { - cssRequest.open('GET', cssFiles[i], true); - cssRequest.send(); -} - -const validatePage = function (url) -{ - if (visited.includes(url) || visited.length > pageLimit - 1) { - return; - } - - // mark url as visited - visited.push(url); - findings[url] = {}; - - // web request - const webRequest = new XMLHttpRequest(); - webRequest.onreadystatechange = function () - { - if (webRequest.readyState === 4 && webRequest.status === 200) { - // replace content - document.open(); - document.write(this.responseText); - document.close(); - - // analyze img alt attribute - const imgAlt = document.querySelectorAll('img:not([alt]), img[alt=""], img[alt=" "]'); - findings[url].img_alt = imgAlt.length; - - // analyze img src - const imgSrc = document.querySelectorAll('img:not([src]), img[src=""], img[src=" "]'); - findings[url].img_src = imgSrc.length; - - // analyze empty link - const aHref = document.querySelectorAll('a:not([alt]), a[href=""], a[href=" "], a[href="#"]'); - findings[url].href_empty = aHref.length; - - /* eslint-disable max-len */ - // analyze inline on* function - const onFunction = document.querySelectorAll('[onafterprint], [onbeforeprint], [onbeforeunload], [onerror], [onhaschange], [onload], [onmessage], [onoffline], [ononline], [onpagehide], [onpageshow], [onpopstate], [onredo], [onresize], [onstorage], [onundo], [onunload], [onblur], [onchage], [oncontextmenu], [onfocus], [onformchange], [onforminput], [oninput], [oninvalid], [onreset], [onselect], [onsubmit], [onkeydown], [onkeypress], [onkeyup], [onclick], [ondblclick], [ondrag], [ondragend], [ondragenter], [ondragleave], [ondragover], [ondragstart], [ondrop], [onmousedown], [onmousemove], [onmouseout], [onmouseover], [onmouseup], [onmousewheel], [onscroll], [onabort], [oncanplay], [oncanplaythrough], [ondurationchange], [onemptied], [onended], [onerror], [onloadeddata], [onloadedmetadata], [onloadstart], [onpause], [onplay], [onplaying], [onprogress], [onratechange], [onreadystatechange], [onseeked], [onseeking], [onstalled], [onsuspend], [ontimeupdate], [onvolumechange], [onwaiting]'); - findings[url].js_on = onFunction.length; - - // analyze missing form element attributes - const formElements = document.querySelectorAll('input:not([id]), input[type=""], select:not([id]), textarea:not([id]), label:not([for]), label[for=""], label[for=" "], input:not([name]), select:not([name]), textarea:not([name]), form:not([id]), form:not([action]), form[action=""], form[action=" "], form[action="#"]'); - findings[url].form_elements = formElements.length; - - // analyze invalid container-children relationship (e.g. empty containers, invalid children) - const invalidContainerChildren = document.querySelectorAll(':not(tr) > td, :not(tr) > th, colgroup *:not(col), :not(colgroup) > col, tr > :not(td):not(th), optgroup > :not(option), :not(select) > option, :not(fieldset) > legend, select > :not(option):not(optgroup), :not(select):not(optgroup) > option, table > *:not(thead):not(tfoot):not(tbody):not(tr):not(colgroup):not(caption)'); - findings[url].invalid_container_children = invalidContainerChildren.length; - /* eslint-enable max-len */ - - // has inline styles - const hasInlineStyles = document.querySelectorAll('*[style]'); - findings[url].form_elements = hasInlineStyles.length; - - // analyze css usage - let cssFound; - for (const i in cssSelectors) { - try { - cssFound = document.querySelectorAll(i.replace(/:hover|:active/gi, '')); - cssSelectors[i] = cssFound === null ? 0 : cssFound.length; - } catch (e) {} - } - - // check other pages - const links = document.querySelectorAll('a'); - const linkLength = links.length; - - for (let i = 0; i < linkLength; ++i) { - if (visited.includes(links[i].href) - || (!links[i].href.startsWith('/') && links[i].href.startsWith('http') && !links[i].href.includes(domain)) - ) { - continue; - } - - validatePage(links[i].href); - } - } - }; - - webRequest.open('GET', url, true); - webRequest.send(); -}; - -validatePage(location.href); - -console.table(findings); -console.table(cssSelectors); diff --git a/Utils/Parser/Markdown.js b/Utils/Parser/Markdown.js old mode 100755 new mode 100644 index d319cb9..0713947 --- a/Utils/Parser/Markdown.js +++ b/Utils/Parser/Markdown.js @@ -3135,7 +3135,7 @@ text = globals.converter._dispatch('completeHTMLDocument.before', text, options, globals); var doctype = 'html', - doctypeParsed = '\n', + doctypeParsed = '\n', title = '', charset = '\n', lang = '', diff --git a/Utils/Parser/license.txt b/Utils/Parser/license.txt old mode 100755 new mode 100644 diff --git a/Utils/oLib.js b/Utils/oLib.js old mode 100755 new mode 100644 index 46f8c54..3415243 --- a/Utils/oLib.js +++ b/Utils/oLib.js @@ -4,7 +4,7 @@ * This library provides useful functionalities for the DOM and other manipulations. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 */ diff --git a/Views/FormView.js b/Views/FormView.js old mode 100755 new mode 100644 index 21428ad..952bd33 --- a/Views/FormView.js +++ b/Views/FormView.js @@ -1,5 +1,4 @@ import { jsOMS } from '../Utils/oLib.js'; -import { Input } from '../UI/Component/Input.js'; /** * Form view. @@ -9,18 +8,18 @@ import { Input } from '../UI/Component/Input.js'; * form elements such as canvas etc. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 * - * @tood Karaka/jsOMS#60 - * On change listener - * Allow to add a on change listener in a form. This should result in automatic submits after changing a form. - * Consider the following cases to submit the form: - * * on Enter (all except textarea) - * * on Change (by using a timer) - * * on Leave (all elements) - * The listener should be defined in the form definition once and in js be applied to all form elements. + * @todo On change listener + * Allow to add a on change listener in a form. This should result in automatic submits after changing a form. + * Consider the following cases to submit the form: + * * on Enter (all except textarea) + * * on Change (by using a timer) + * * on Leave (all elements) + * The listener should be defined in the form definition once and in js be applied to all form elements. + * https://github.com/Karaka-Management/jsOMS/issues/60 */ export class FormView { @@ -776,27 +775,6 @@ export class FormView } else { this.action = 'EMPTY'; } - - const elements = this.getFormElements(); - const length = elements.length; - - for (let i = 0; i < length; ++i) { - switch (elements[i].tagName.toLowerCase()) { - case 'input': - Input.bindElement(elements[i]); - break; - case 'select': - // this.bindSelect(elements[i]); - break; - case 'textarea': - // this.bindTextarea(elements[i]); - break; - case 'button': - // this.bindButton(elements[i]); - break; - default: - } - } }; getElementsToBind (e = null) diff --git a/Views/TableView.js b/Views/TableView.js old mode 100755 new mode 100644 index 681862d..b980ead --- a/Views/TableView.js +++ b/Views/TableView.js @@ -2,7 +2,7 @@ * Table view. * * @copyright Dennis Eichhorn - * @license OMS License 2.0 + * @license OMS License 2.2 * @version 1.0.0 * @since 1.0.0 * diff --git a/composer.json b/composer.json old mode 100755 new mode 100644 index 14e79d6..aa9317a --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ } ], "require-dev": { - "squizlabs/php_codesniffer": ">=3.7", + "phpcsstandards/php_codesniffer": ">=3.7", "phpstan/phpstan": ">=0.12.18" } } diff --git a/composer.lock b/composer.lock old mode 100755 new mode 100644 index 8d08b82..4cb51dc --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,102 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6f994d7ac9a0187ad572589bd8174666", + "content-hash": "1e66c17ce720238564662eda5e375608", "packages": [], "packages-dev": [ { - "name": "phpstan/phpstan", - "version": "1.10.35", + "name": "phpcsstandards/php_codesniffer", + "version": "3.9.2", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "e730e5facb75ffe09dfb229795e8c01a459f26c3" + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e730e5facb75ffe09dfb229795e8c01a459f26c3", - "reference": "e730e5facb75ffe09dfb229795e8c01a459f26c3", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/aac1f6f347a5c5ac6bc98ad395007df00990f480", + "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "abandoned": "squizlabs/php_codesniffer", + "time": "2024-04-23T20:25:34+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e524358f930e41a2b4cca1320e3b04fc26b39e0b", + "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b", "shasum": "" }, "require": { @@ -61,70 +142,9 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2023-09-19T15:27:56+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.7.2", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" - }, - "time": "2023-02-22T23:07:41+00:00" + "time": "2024-05-15T08:00:59+00:00" } ], "aliases": [], diff --git a/tests/Account/AccountManagerTest.js b/tests/Account/AccountManagerTest.js old mode 100755 new mode 100644 diff --git a/tests/Account/AccountTest.js b/tests/Account/AccountTest.js old mode 100755 new mode 100644 diff --git a/tests/Account/AccountTypeTest.js b/tests/Account/AccountTypeTest.js old mode 100755 new mode 100644 diff --git a/tests/Asset/AssetManagerTest.js b/tests/Asset/AssetManagerTest.js old mode 100755 new mode 100644 diff --git a/tests/Config/OptionsTest.js b/tests/Config/OptionsTest.js old mode 100755 new mode 100644 diff --git a/tests/DataStorage/LocalStorageTest.js b/tests/DataStorage/LocalStorageTest.js old mode 100755 new mode 100644 diff --git a/tests/Event/EventManagerTest.js b/tests/Event/EventManagerTest.js old mode 100755 new mode 100644 diff --git a/tests/Log/LogLevelTest.js b/tests/Log/LogLevelTest.js old mode 100755 new mode 100644 diff --git a/tests/Log/LoggerTest.js b/tests/Log/LoggerTest.js old mode 100755 new mode 100644 diff --git a/tests/Math/MathProcessorTest.js b/tests/Math/MathProcessorTest.js old mode 100755 new mode 100644 diff --git a/tests/Message/Notification/NotificationLevelTest.js b/tests/Message/Notification/NotificationLevelTest.js old mode 100755 new mode 100644 diff --git a/tests/Message/Notification/NotificationManagerTest.js b/tests/Message/Notification/NotificationManagerTest.js old mode 100755 new mode 100644 diff --git a/tests/Message/Notification/NotificationMessageTest.js b/tests/Message/Notification/NotificationMessageTest.js old mode 100755 new mode 100644 diff --git a/tests/Message/Notification/NotificationTypeTest.js b/tests/Message/Notification/NotificationTypeTest.js old mode 100755 new mode 100644 diff --git a/tests/Message/Request/RequestMethodTest.js b/tests/Message/Request/RequestMethodTest.js old mode 100755 new mode 100644 diff --git a/tests/Message/Request/RequestTypeTest.js b/tests/Message/Request/RequestTypeTest.js old mode 100755 new mode 100644 diff --git a/tests/Message/Response/ResponseTypeTest.js b/tests/Message/Response/ResponseTypeTest.js old mode 100755 new mode 100644 diff --git a/tests/SpecRunner.html b/tests/SpecRunner.html old mode 100755 new mode 100644 diff --git a/tests/Uri/HttpUriTest.js b/tests/Uri/HttpUriTest.js old mode 100755 new mode 100644 diff --git a/tests/Uri/UriFactoryTest.js b/tests/Uri/UriFactoryTest.js old mode 100755 new mode 100644 index 9b50e99..4216a16 --- a/tests/Uri/UriFactoryTest.js +++ b/tests/Uri/UriFactoryTest.js @@ -66,16 +66,16 @@ describe('UriFactoryTest', function () { it('Testing global queries', function () { - let uri = 'www.test-uri.com?id={@ID}&test={.mTest}&two={/path}&hash={#hash}&found={/not}?v={/valid2}', + let uri = 'www.test-uri.com?id={@ID}&test={.mTest}&two={/path}&hash={#hash}&found={/not}?v={?valid2}', vars = { '@ID' : 1, '.mTest': 'someString', '/path' : 'PATH', '#hash' : 'test', }, - expected = 'www.test-uri.com?id=1&test=someString&two=PATH&hash=test&found=ERROR%20PATH&v=query4'; + expected = 'www.test-uri.com?id=1&test=someString&two=PATH&hash=test&found=null&v=query4'; - expect(UriFactory.setQuery('/valid2', 'query4')).toBeTruthy(); + expect(UriFactory.setQuery('?valid2', 'query4')).toBeTruthy(); expect(UriFactory.build(uri, vars)).toBe(expected); }); }); diff --git a/tests/Views/FormViewTest.js b/tests/Views/FormViewTest.js old mode 100755 new mode 100644