From 89acb321f9e2d78a8b601f123c31b39c8554d122 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 2 Apr 2019 22:46:48 +0200 Subject: [PATCH] Use js modules --- Account/Account.js | 51 +- Account/AccountManager.js | 121 +- Account/AccountType.js | 15 +- Asset/AssetManager.js | 300 +++-- Auth/Auth.js | 175 ++- Autoloader.js | 190 ++- DataStorage/CacheManager.js | 18 +- DataStorage/LocalStorage.js | 57 +- DataStorage/StorageManager.js | 16 +- Dispatcher/Dispatcher.js | 16 +- Event/EventManager.js | 457 ++++--- Log/LogLevel.js | 28 +- Log/Logger.js | 638 +++++----- Message/Notification/App/AppNotification.js | 112 +- .../Browser/BrowserNotification.js | 126 +- Message/Notification/NotificationLevel.js | 19 +- Message/Notification/NotificationManager.js | 116 +- Message/Notification/NotificationMessage.js | 41 +- Message/Notification/NotificationType.js | 16 +- Message/Request/BrowserType.js | 28 +- Message/Request/OSType.js | 62 +- Message/Request/Request.js | 737 ++++++----- Message/Request/RequestMethod.js | 22 +- Message/Request/RequestType.js | 20 +- Message/Response/Response.js | 82 +- Message/Response/ResponseManager.js | 118 +- Message/Response/ResponseType.js | 24 +- Model/Action/Dom/Datalist/Append.js | 2 +- Model/Action/Dom/Datalist/Clear.js | 2 +- Model/Action/Dom/Focus.js | 2 +- Model/Action/Dom/GetValue.js | 2 +- Model/Action/Dom/Hide.js | 2 +- Model/Action/Dom/Popup.js | 2 +- Model/Action/Dom/Remove.js | 2 +- Model/Action/Dom/RemoveValue.js | 2 +- Model/Action/Dom/SetValue.js | 2 +- Model/Action/Dom/Show.js | 2 +- Model/Action/Dom/Table/Append.js | 2 +- Model/Action/Dom/Table/Clear.js | 2 +- Model/Action/Event/Prevent.js | 2 +- Model/Action/Message/Log.js | 2 +- Model/Action/Message/Request.js | 2 +- Model/Action/Utils/DataCollector.js | 2 +- Model/Action/Utils/Timer.js | 2 +- Model/Action/Validate/Keypress.js | 2 +- Model/Message/DomAction.js | 2 +- Model/Message/DomActionType.js | 26 +- Model/Message/FormValidation.js | 2 +- Model/Message/Notify.js | 2 +- Model/Message/NotifyType.js | 17 +- Model/Message/Redirect.js | 6 +- Model/Message/Reload.js | 2 +- Module/ModuleFactory.js | 55 +- Module/ModuleManager.js | 69 +- UI/ActionManager.js | 338 +++-- UI/Component/AdvancedInput.js | 567 +++++---- UI/Component/Form.js | 543 ++++---- UI/Component/Input.js | 294 +++-- UI/Component/Tab.js | 218 ++-- UI/Component/Table.js | 1094 ++++++++--------- UI/DragNDrop.js | 218 ++-- UI/GeneralUI.js | 212 ++-- UI/Input/InputManager.js | 104 +- UI/Input/Keyboard/KeyboardManager.js | 192 ++- UI/Input/Mouse/ClickType.js | 18 +- UI/Input/Mouse/EventType.js | 18 +- UI/Input/Mouse/MouseManager.js | 214 ++-- UI/Input/Touch/TouchManager.js | 216 ++-- UI/Input/Voice/ReadManager.js | 208 ++-- UI/Input/Voice/VoiceManager.js | 284 +++-- UI/UIManager.js | 299 +++-- UnhandledException.js | 2 +- Uri/Http.js | 558 +++++---- Uri/UriFactory.js | 483 ++++---- Views/FormView.js | 833 +++++++------ Views/TableView.js | 274 ++--- 76 files changed, 5341 insertions(+), 5668 deletions(-) diff --git a/Account/Account.js b/Account/Account.js index 8d64267..06228f5 100644 --- a/Account/Account.js +++ b/Account/Account.js @@ -6,33 +6,26 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - jsOMS.Autoloader.defineNamespace('jsOMS.Account'); - - jsOMS.Account.Account = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () - { - this.id = 0; - }; - - /** - * Get id. - * - * @return {int} - * - * @since 1.0.0 - */ - getId () - { - return this.id; - }; +export class Account { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + this.id = 0; }; -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file + + /** + * Get id. + * + * @return {int} + * + * @since 1.0.0 + */ + getId () + { + return this.id; + }; +}; \ No newline at end of file diff --git a/Account/AccountManager.js b/Account/AccountManager.js index 3ea3289..897d77f 100644 --- a/Account/AccountManager.js +++ b/Account/AccountManager.js @@ -6,73 +6,66 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class AccountManager { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + this.accounts = []; + }; - jsOMS.Autoloader.defineNamespace('jsOMS.Account'); + /** + * Add account. + * + * @param {Object} account Account + * + * @return {void} + * + * @since 1.0.0 + */ + add (account) + { + this.accounts[account.getId()] = account; + }; - jsOMS.Account.AccountManager = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () - { - this.accounts = []; - }; + /** + * Remove account. + * + * @param {int} id Account id + * + * @return {void} + * + * @since 1.0.0 + */ + remove (id) + { + if (typeof this.accounts[id] !== 'undefined') { + delete this.accounts[id]; - /** - * Add account. - * - * @param {Object} account Account - * - * @return {void} - * - * @since 1.0.0 - */ - add (account) - { - this.accounts[account.getId()] = account; - }; + return true; + } - /** - * Remove account. - * - * @param {int} id Account id - * - * @return {void} - * - * @since 1.0.0 - */ - remove (id) - { - if (typeof this.accounts[id] !== 'undefined') { - delete this.accounts[id]; + return false; + }; - return true; - } + /** + * Get account by id. + * + * @param {int} id Account id + * + * @return {null|Object} + * + * @since 1.0.0 + */ + get (id) + { + if (this.accounts[id]) { + return this.accounts[id]; + } - return false; - }; - - /** - * Get account by id. - * - * @param {int} id Account id - * - * @return {null|Object} - * - * @since 1.0.0 - */ - get (id) - { - if (this.accounts[id]) { - return this.accounts[id]; - } - - return null; - }; - } -}(window.jsOMS = window.jsOMS || {})); + return null; + }; +}; diff --git a/Account/AccountType.js b/Account/AccountType.js index eae3133..f33c217 100644 --- a/Account/AccountType.js +++ b/Account/AccountType.js @@ -6,14 +6,7 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - jsOMS.Autoloader.defineNamespace('jsOMS.Account'); - - jsOMS.Account.AccountType = Object.freeze({ - USER: 0, - GROUP: 1 - }); -}(window.jsOMS = window.jsOMS || {})); +export const AccountType = Object.freeze({ + USER: 0, + GROUP: 1 +}); diff --git a/Asset/AssetManager.js b/Asset/AssetManager.js index cce5185..c20dd61 100644 --- a/Asset/AssetManager.js +++ b/Asset/AssetManager.js @@ -6,157 +6,151 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - jsOMS.Asset = {}; - - jsOMS.Asset.AssetManager = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () - { - this.assets = {}; - this.registerLoadedAssets(); - }; - - /** - * Register all loaded assets. - * - * @return {void} - * - * @since 1.0.0 - */ - registerLoadedAssets () - { - const scripts = document.getElementsByTagName('script'), - length = !scripts ? 0 : scripts.length; - - this.assets = {}; - - for (let i = 0; i < length; ++i) { - this.assets[jsOMS.hash(scripts[i].src)] = scripts[i].src; - } - }; - - /** - * Load asset. - * - * @param {string} path Asset path - * @param {string} filetype Filetype of the asset - * @param {requestCallback} [callback] Callback after load - * - * @return {string|boolean} - * - * @since 1.0.0 - */ - load (path, filetype, callback) - { - let hash; - - if (!this.assets[(hash = jsOMS.hash(path))]) { - let fileref = null; - - if (filetype === 'js') { - fileref = document.createElement('script'); - fileref.setAttribute('type', 'text/javascript'); - fileref.setAttribute('src', path); - - if (typeof fileref !== 'undefined') { - const head = document.getElementsByTagName('head'); - - if (head) { - head[0].appendChild(fileref); - } - } - - this.assets[hash] = path; - } else if (filetype === 'css') { - fileref = document.createElement('link'); - fileref.setAttribute('rel', 'stylesheet'); - fileref.setAttribute('type', 'text/css'); - fileref.setAttribute('href', path); - - if (typeof fileref !== 'undefined') { - const head = document.getElementsByTagName('head'); - - if (head) { - head[0].appendChild(fileref); - } - } - - this.assets[hash] = path; - } else if (filetype === 'img') { - /** global: Image */ - this.assets[hash] = new Image(); - this.assets[hash].src = path; - } else if (filetype === 'audio') { - // TODO: implement audio asset - } else if (filetype === 'video') { - // TODO: implement video asset - } - - if (callback) { - fileref.onreadystatechange () - { - if (this.readyState === 'complete') { - callback(); - } - }; - - fileref.onload = callback(); - } - - return hash; - } - - return false; - }; - - /** - * Get asset. - * - * @param {string} key Key of the asset - * - * @return {null|string} - * - * @since 1.0.0 - */ - get (key) - { - key = jsOMS.hash(key); - - if (this.assets[key]) { - return this.assets[key]; - } - - return null; - }; - - /** - * Remove asset. - * - * @param {string} key Key of the asset - * - * @return {boolean} - * - * @since 1.0.0 - */ - remove (key) - { - key = jsOMS.hash(key); - - if (typeof this.assets[key] !== 'undefined') { - delete this.assets[key]; - - return true; - } - - return false; - }; +export class AssetManager { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + this.assets = {}; + this.registerLoadedAssets(); }; -}(window.jsOMS = window.jsOMS || {})); + + /** + * Register all loaded assets. + * + * @return {void} + * + * @since 1.0.0 + */ + registerLoadedAssets () + { + const scripts = document.getElementsByTagName('script'), + length = !scripts ? 0 : scripts.length; + + this.assets = {}; + + for (let i = 0; i < length; ++i) { + this.assets[jsOMS.hash(scripts[i].src)] = scripts[i].src; + } + }; + + /** + * Load asset. + * + * @param {string} path Asset path + * @param {string} filetype Filetype of the asset + * @param {requestCallback} [callback] Callback after load + * + * @return {string|boolean} + * + * @since 1.0.0 + */ + load (path, filetype, callback) + { + let hash; + + if (!this.assets[(hash = jsOMS.hash(path))]) { + let fileref = null; + + if (filetype === 'js') { + fileref = document.createElement('script'); + fileref.setAttribute('type', 'text/javascript'); + fileref.setAttribute('src', path); + + if (typeof fileref !== 'undefined') { + const head = document.getElementsByTagName('head'); + + if (head) { + head[0].appendChild(fileref); + } + } + + this.assets[hash] = path; + } else if (filetype === 'css') { + fileref = document.createElement('link'); + fileref.setAttribute('rel', 'stylesheet'); + fileref.setAttribute('type', 'text/css'); + fileref.setAttribute('href', path); + + if (typeof fileref !== 'undefined') { + const head = document.getElementsByTagName('head'); + + if (head) { + head[0].appendChild(fileref); + } + } + + this.assets[hash] = path; + } else if (filetype === 'img') { + /** global: Image */ + this.assets[hash] = new Image(); + this.assets[hash].src = path; + } else if (filetype === 'audio') { + // TODO: implement audio asset + } else if (filetype === 'video') { + // TODO: implement video asset + } + + if (callback) { + fileref.onreadystatechange () + { + if (this.readyState === 'complete') { + callback(); + } + }; + + fileref.onload = callback(); + } + + return hash; + } + + return false; + }; + + /** + * Get asset. + * + * @param {string} key Key of the asset + * + * @return {null|string} + * + * @since 1.0.0 + */ + get (key) + { + key = jsOMS.hash(key); + + if (this.assets[key]) { + return this.assets[key]; + } + + return null; + }; + + /** + * Remove asset. + * + * @param {string} key Key of the asset + * + * @return {boolean} + * + * @since 1.0.0 + */ + remove (key) + { + key = jsOMS.hash(key); + + if (typeof this.assets[key] !== 'undefined') { + delete this.assets[key]; + + return true; + } + + return false; + }; +}; + diff --git a/Auth/Auth.js b/Auth/Auth.js index 09e4e1f..5518f03 100644 --- a/Auth/Auth.js +++ b/Auth/Auth.js @@ -6,95 +6,88 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - jsOMS.Autoloader.defineNamespace('jsOMS.Auth'); - - jsOMS.Auth.Auth = class { - /** - * @constructor - * - * @param {string} uri Login uri - * - * @since 1.0.0 - */ - constructor (uri) - { - this.account = null; - this.uri = uri; - }; - - /** - * Set account for authentication. - * - * @param {Object} account Account - * - * @since 1.0.0 - */ - setAccount (account) - { - this.account = account; - }; - - /** - * Get account. - * - * @return {Object} - * - * @since 1.0.0 - */ - getAccount () - { - return this.account; - }; - - /** - * Login account. - * - * @return {void} - * - * @since 1.0.0 - */ - login () - { - const authRequest = new jsOMS.Message.Request.Request(); - - authRequest.setUri(this.uri); - authRequest.setMethod(jsOMS.Message.Request.RequestMethod.POST); - authRequest.setResponseType(jsOMS.Message.Request.RequestType.JSON); - authRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); - authRequest.setSuccess(function (xhr) - { - this.loginResult(xhr); - }); - - authRequest.send(); - }; - - /** - * Logout account. - * - * @return {void} - * - * @since 1.0.0 - */ - logout () - { - location.reload(); - }; - - /** - * Handle login result. - * - * @return {void} - * - * @since 1.0.0 - */ - loginResult (xhr) - { - location.reload(); - }; +export class Auth { + /** + * @constructor + * + * @param {string} uri Login uri + * + * @since 1.0.0 + */ + constructor (uri) + { + this.account = null; + this.uri = uri; }; -}(window.jsOMS = window.jsOMS || {})); + + /** + * Set account for authentication. + * + * @param {Object} account Account + * + * @since 1.0.0 + */ + setAccount (account) + { + this.account = account; + }; + + /** + * Get account. + * + * @return {Object} + * + * @since 1.0.0 + */ + getAccount () + { + return this.account; + }; + + /** + * Login account. + * + * @return {void} + * + * @since 1.0.0 + */ + login () + { + const authRequest = new jsOMS.Message.Request.Request(); + + authRequest.setUri(this.uri); + authRequest.setMethod(jsOMS.Message.Request.RequestMethod.POST); + authRequest.setResponseType(jsOMS.Message.Request.RequestType.JSON); + authRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + authRequest.setSuccess(function (xhr) + { + this.loginResult(xhr); + }); + + authRequest.send(); + }; + + /** + * Logout account. + * + * @return {void} + * + * @since 1.0.0 + */ + logout () + { + location.reload(); + }; + + /** + * Handle login result. + * + * @return {void} + * + * @since 1.0.0 + */ + loginResult (xhr) + { + location.reload(); + }; +}; diff --git a/Autoloader.js b/Autoloader.js index 7d77f7b..439a8f9 100644 --- a/Autoloader.js +++ b/Autoloader.js @@ -1,3 +1,5 @@ +import { AssetManager } from './Asset/AssetManager.js'; + /** * Autoloader. * @@ -11,108 +13,104 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) + export const Autoloader = {}; + +Autoloader.loaded = []; +Autoloader.namespaced = []; +Autoloader.assetLoader = new AssetManager(); + +/** + * Define namespace + * + * @param {string} namespace Namespace + * + * @return {void} + * + * @since 1.0.0 + */ +Autoloader.defineNamespace = function (namespace) { - "use strict"; + if (Autoloader.namespaced.indexOf(namespace) === -1) { + let paths = namespace.split('.'); + paths.splice(0, 1); - jsOMS.Autoloader = {}; - jsOMS.Autoloader.loaded = []; - jsOMS.Autoloader.namespaced = []; - jsOMS.Autoloader.assetLoader = new jsOMS.Asset.AssetManager(); - - /** - * Define namespace - * - * @param {string} namespace Namespace - * - * @return {void} - * - * @since 1.0.0 - */ - jsOMS.Autoloader.defineNamespace = function (namespace) - { - if (jsOMS.Autoloader.namespaced.indexOf(namespace) === -1) { - let paths = namespace.split('.'); - paths.splice(0, 1); - - const length = paths.length; - let current = jsOMS; - - for (let i = 0; i < length; ++i) { - if (typeof current[paths[i]] === 'undefined') { - current[paths[i]] = {}; - } - - current = current[paths[i]]; - } - - jsOMS.Autoloader.namespaced.push(namespace); - } - }; - - /** - * Collect all loaded javascript files - * - * @return {void} - * - * @since 1.0.0 - */ - jsOMS.Autoloader.initPreloaded = function () - { - const scripts = document.getElementsByTagName('script'), - length = !scripts ? 0 : scripts.length; + const length = paths.length; + let current = jsOMS; for (let i = 0; i < length; ++i) { - /** global: URL */ - /** @var {string} URL */ - scripts[i].src.replace(URL + '/', ''); - - if (jsOMS.Autoloader.loaded.indexOf(scripts[i].src) === -1) { - jsOMS.Autoloader.loaded.push(scripts[i].src); + if (typeof current[paths[i]] === 'undefined') { + current[paths[i]] = {}; } - } - }; - /** - * Add loaded script - * - * @param {string} file Script URI - * - * @return {void} - * - * @since 1.0.0 - */ - jsOMS.Autoloader.addPreloaded = function (file) - { - if (jsOMS.Autoloader.loaded.indexOf(file) === -1) { - jsOMS.Autoloader.loaded.push(file); - } - }; - - /** - * Include script - * - * @param {string} file Script URI - * @param {function} callback Callback after script loading - * - * @return {void} - * - * @since 1.0.0 - */ - jsOMS.Autoloader.include = function (file, callback) - { - const length = file.length; - - for (let i = 0; i < length; ++i) { - if (jsOMS.Autoloader.loaded.indexOf(file) === -1) { - this.assetLoader.load(file, 'js'); - - jsOMS.Autoloader.loaded.push(file); - } + current = current[paths[i]]; } - if (typeof callback !== 'undefined' && callback !== null) { - callback(); + Autoloader.namespaced.push(namespace); + } +}; + +/** + * Collect all loaded javascript files + * + * @return {void} + * + * @since 1.0.0 + */ +Autoloader.initPreloaded = function () +{ + const scripts = document.getElementsByTagName('script'), + length = !scripts ? 0 : scripts.length; + + for (let i = 0; i < length; ++i) { + /** global: URL */ + /** @var {string} URL */ + scripts[i].src.replace(URL + '/', ''); + + if (Autoloader.loaded.indexOf(scripts[i].src) === -1) { + Autoloader.loaded.push(scripts[i].src); } - }; -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file + } +}; + +/** + * Add loaded script + * + * @param {string} file Script URI + * + * @return {void} + * + * @since 1.0.0 + */ +Autoloader.addPreloaded = function (file) +{ + if (Autoloader.loaded.indexOf(file) === -1) { + Autoloader.loaded.push(file); + } +}; + +/** + * Include script + * + * @param {string} file Script URI + * @param {function} callback Callback after script loading + * + * @return {void} + * + * @since 1.0.0 + */ +Autoloader.include = function (file, callback) +{ + const length = file.length; + + for (let i = 0; i < length; ++i) { + if (Autoloader.loaded.indexOf(file) === -1) { + this.assetLoader.load(file, 'js'); + + Autoloader.loaded.push(file); + } + } + + if (typeof callback !== 'undefined' && callback !== null) { + callback(); + } +}; diff --git a/DataStorage/CacheManager.js b/DataStorage/CacheManager.js index f4d2eae..a83bc84 100644 --- a/DataStorage/CacheManager.js +++ b/DataStorage/CacheManager.js @@ -1,14 +1,6 @@ -(function (jsOMS) { - "use strict"; +export class CacheManager { + constructor () + { - jsOMS.Autoloader.defineNamespace('jsOMS.DataStorage'); - - // TODO: create comments - - jsOMS.DataStorage.CacheManager = class { - constructor () - { - - } - }; -}(window.jsOMS = window.jsOMS || {})); + } +}; diff --git a/DataStorage/LocalStorage.js b/DataStorage/LocalStorage.js index ff356e2..7fa69d2 100644 --- a/DataStorage/LocalStorage.js +++ b/DataStorage/LocalStorage.js @@ -6,36 +6,29 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - jsOMS.Autoloader.defineNamespace('jsOMS.DataStorage'); - - jsOMS.DataStorage.LocalStorage = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () - { - }; - - /** - * Is local storage available? - * - * @return {boolean} - * - * @since 1.0.0 - */ - static available() - { - try { - return 'localStorage' in window && window.localStorage !== null; - } catch (e) { - return false; - } - }; +export class LocalStorage { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { }; -}(window.jsOMS = window.jsOMS || {})); + + /** + * Is local storage available? + * + * @return {boolean} + * + * @since 1.0.0 + */ + static available() + { + try { + return 'localStorage' in window && window.localStorage !== null; + } catch (e) { + return false; + } + }; +}; diff --git a/DataStorage/StorageManager.js b/DataStorage/StorageManager.js index 94e4501..73c3bfa 100644 --- a/DataStorage/StorageManager.js +++ b/DataStorage/StorageManager.js @@ -1,11 +1,5 @@ -(function (jsOMS) { - "use strict"; - - jsOMS.Autoloader.defineNamespace('jsOMS.DataStorage'); - - jsOMS.DataStorage.StorageManager = class { - constructor () - { - }; - } -}(window.jsOMS = window.jsOMS || {})); +export class StorageManager { + constructor () + { + }; +}; diff --git a/Dispatcher/Dispatcher.js b/Dispatcher/Dispatcher.js index 0d5ea62..9fe6db0 100644 --- a/Dispatcher/Dispatcher.js +++ b/Dispatcher/Dispatcher.js @@ -1,11 +1,5 @@ -(function (jsOMS) { - "use strict"; - - jsOMS.Autoloader.defineNamespace('jsOMS.Dispatcher'); - - jsOMS.Dispatcher.Dispatcher = class { - constructor () - { - }; - } -}(window.jsOMS = window.jsOMS || {})); +export class Dispatcher { + constructor () + { + }; +}; diff --git a/Event/EventManager.js b/Event/EventManager.js index c5f475c..55b8ed4 100644 --- a/Event/EventManager.js +++ b/Event/EventManager.js @@ -1,3 +1,5 @@ +import { Logger } from '../Log/Logger.js'; + /** * Request manager class. * @@ -8,252 +10,245 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class EventManager { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + this.logger = Logger.getInstance(); + this.groups = {}; + this.callbacks = {}; + }; - jsOMS.Autoloader.defineNamespace('jsOMS.Event'); + /** + * Add event group (element) + * + * Adding the same event overwrites the existing one as "waiting" + * + * @param {string|int} group Group id + * @param {string|int} id Event id + * + * @return {void} + * + * @since 1.0.0 + */ + addGroup (group, id) + { + if (typeof this.groups[group] === 'undefined') { + this.groups[group] = {}; + } - jsOMS.Event.EventManager = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () - { - this.logger = jsOMS.Log.Logger.getInstance(); - this.groups = {}; - this.callbacks = {}; - }; + this.groups[group][id] = false; + }; - /** - * Add event group (element) - * - * Adding the same event overwrites the existing one as "waiting" - * - * @param {string|int} group Group id - * @param {string|int} id Event id - * - * @return {void} - * - * @since 1.0.0 - */ - addGroup (group, id) - { - if (typeof this.groups[group] === 'undefined') { - this.groups[group] = {}; - } - - this.groups[group][id] = false; - }; - - /** - * Resets the group status - * - * @param {string|int} group Group id - * - * @return {void} - * - * @since 1.0.0 - */ - reset (group) - { - for (let id in this.groups[group]) { - if (this.groups[group].hasOwnProperty(id)) { - this.groups[group][id] = false; - } - } - }; - - /** - * Does group have outstanding events - * - * @param {string|int} group Group id - * - * @return {boolean} - * - * @since 1.0.0 - */ - hasOutstanding (group) - { - if (typeof this.groups[group] === 'undefined') { - return false; - } - - for (let id in this.groups[group]) { - if (!this.groups[group].hasOwnProperty(id) || !this.groups[group][id]) { - return true; - } + /** + * Resets the group status + * + * @param {string|int} group Group id + * + * @return {void} + * + * @since 1.0.0 + */ + reset (group) + { + for (let id in this.groups[group]) { + if (this.groups[group].hasOwnProperty(id)) { + this.groups[group][id] = false; } + } + }; + /** + * Does group have outstanding events + * + * @param {string|int} group Group id + * + * @return {boolean} + * + * @since 1.0.0 + */ + hasOutstanding (group) + { + if (typeof this.groups[group] === 'undefined') { return false; - }; + } - /** - * Trigger event finished - * - * Executes the callback specified for this group if all events are finished - * - * @param {string|int} group Group id - * @param {string|int} [id] Event id - * @param {Object} [data] Data for event - * - * @return {boolean} - * - * @since 1.0.0 - */ - trigger (group, id = '', data = null) - { - if (this.callbacks.hasOwnProperty(group)) { - return this.triggerSingleEvent(group, id, data); + for (let id in this.groups[group]) { + if (!this.groups[group].hasOwnProperty(id) || !this.groups[group][id]) { + return true; } + } - const allGroups = Object.keys(this.callbacks), - regex = new RegExp(group), - length = allGroups.length; + return false; + }; - let result = false; + /** + * Trigger event finished + * + * Executes the callback specified for this group if all events are finished + * + * @param {string|int} group Group id + * @param {string|int} [id] Event id + * @param {Object} [data] Data for event + * + * @return {boolean} + * + * @since 1.0.0 + */ + trigger (group, id = '', data = null) + { + if (this.callbacks.hasOwnProperty(group)) { + return this.triggerSingleEvent(group, id, data); + } + + const allGroups = Object.keys(this.callbacks), + regex = new RegExp(group), + length = allGroups.length; + + let result = false; + + for (let i = 0; i < length; ++i) { + if (regex.test(allGroups[i])) { + result = result && this.triggerSingleEvent(allGroups[i], id, data); + } + } + + return result; + }; + + /** + * Trigger event finished + * + * Executes the callback specified for this group if all events are finished + * + * @param {string|int} group Group id + * @param {string|int} [id] Event id + * @param {Object} [data] Data for event + * + * @return {boolean} + * + * @since 1.0.0 + */ + triggerSingleEvent (group, id = '', data = null) + { + if (Math.abs(Date.now() - this.callbacks[group].lastRun) < 500) { + return false; + } + + if (typeof this.groups[group] !== 'undefined') { + this.groups[group][id] = true; + } + + if (!this.hasOutstanding(group)) { + const length = this.callbacks[group].callbacks.length; + this.callbacks[group].lastRun = Date.now(); for (let i = 0; i < length; ++i) { - if (regex.test(allGroups[i])) { - result = result && this.triggerSingleEvent(allGroups[i], id, data); - } + this.callbacks[group].callbacks[i](data); } - return result; - }; - - /** - * Trigger event finished - * - * Executes the callback specified for this group if all events are finished - * - * @param {string|int} group Group id - * @param {string|int} [id] Event id - * @param {Object} [data] Data for event - * - * @return {boolean} - * - * @since 1.0.0 - */ - triggerSingleEvent (group, id = '', data = null) - { - if (Math.abs(Date.now() - this.callbacks[group].lastRun) < 500) { - return false; + if (this.callbacks[group].remove) { + this.detach(group); + } else if (this.callbacks[group].reset) { + this.reset(group); } - if (typeof this.groups[group] !== 'undefined') { - this.groups[group][id] = true; - } - - if (!this.hasOutstanding(group)) { - const length = this.callbacks[group].callbacks.length; - this.callbacks[group].lastRun = Date.now(); - - for (let i = 0; i < length; ++i) { - this.callbacks[group].callbacks[i](data); - } - - if (this.callbacks[group].remove) { - this.detach(group); - } else if (this.callbacks[group].reset) { - this.reset(group); - } - - return true; - } - - return false; - }; - - /** - * Detach event - * - * @param {string|int} group Group id - * - * @return {void} - * - * @since 1.0.0 - */ - detach (group) - { - return this.detachCallback(group) | this.detachGroup(group); - }; - - /** - * Detach callback - * - * @param {string|int} group Group id - * - * @return {void} - * - * @since 1.0.0 - */ - detachCallback(group) - { - if (this.callbacks.hasOwnProperty(group)) { - delete this.callbacks[group]; - - return true; - } - - return false; - }; - - /** - * Detach group - * - * @param {string|int} group Group id - * - * @return {void} - * - * @since 1.0.0 - */ - detachGroup(group) - { - if (this.groups.hasOwnProperty(group)) { - delete this.groups[group]; - - return true; - } - - return false; - }; - - /** - * Attach callback to event group - * - * @param {string|int} group Group id - * @param {function} callback Callback or route for the event - * @param {boolean} [remove] Should be removed after execution - * @param {boolean} [reset] Reset after triggering - * - * @return {boolean} - * - * @since 1.0.0 - */ - attach (group, callback, remove = false, reset = false) - { - if (!this.callbacks.hasOwnProperty(group)) { - this.callbacks[group] = {remove: remove, reset: reset, callbacks: [], lastRun: 0}; - } - - this.callbacks[group].callbacks.push(callback); - return true; - }; + } - /** - * Count events - * - * @return {int} - * - * @since 1.0.0 - */ - count () - { - return Object.keys(this.callbacks).length; - }; - } -}(window.jsOMS = window.jsOMS || {})); + return false; + }; + + /** + * Detach event + * + * @param {string|int} group Group id + * + * @return {void} + * + * @since 1.0.0 + */ + detach (group) + { + return this.detachCallback(group) | this.detachGroup(group); + }; + + /** + * Detach callback + * + * @param {string|int} group Group id + * + * @return {void} + * + * @since 1.0.0 + */ + detachCallback(group) + { + if (this.callbacks.hasOwnProperty(group)) { + delete this.callbacks[group]; + + return true; + } + + return false; + }; + + /** + * Detach group + * + * @param {string|int} group Group id + * + * @return {void} + * + * @since 1.0.0 + */ + detachGroup(group) + { + if (this.groups.hasOwnProperty(group)) { + delete this.groups[group]; + + return true; + } + + return false; + }; + + /** + * Attach callback to event group + * + * @param {string|int} group Group id + * @param {function} callback Callback or route for the event + * @param {boolean} [remove] Should be removed after execution + * @param {boolean} [reset] Reset after triggering + * + * @return {boolean} + * + * @since 1.0.0 + */ + attach (group, callback, remove = false, reset = false) + { + if (!this.callbacks.hasOwnProperty(group)) { + this.callbacks[group] = {remove: remove, reset: reset, callbacks: [], lastRun: 0}; + } + + this.callbacks[group].callbacks.push(callback); + + return true; + }; + + /** + * Count events + * + * @return {int} + * + * @since 1.0.0 + */ + count () + { + return Object.keys(this.callbacks).length; + }; +}; \ No newline at end of file diff --git a/Log/LogLevel.js b/Log/LogLevel.js index ca9b32d..62e4c45 100644 --- a/Log/LogLevel.js +++ b/Log/LogLevel.js @@ -6,21 +6,13 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.Log */ - jsOMS.Autoloader.defineNamespace('jsOMS.Log'); - - jsOMS.Log.LogLevel = Object.freeze({ - EMERGENCY: 'emergency', - ALERT: 'alert', - CRITICAL: 'critical', - ERROR: 'error', - WARNING: 'warning', - NOTICE: 'notice', - INFO: 'info', - DEBUG: 'debug' - }); -}(window.jsOMS = window.jsOMS || {})); +export const LogLevel = Object.freeze({ + EMERGENCY: 'emergency', + ALERT: 'alert', + CRITICAL: 'critical', + ERROR: 'error', + WARNING: 'warning', + NOTICE: 'notice', + INFO: 'info', + DEBUG: 'debug' +}); diff --git a/Log/Logger.js b/Log/Logger.js index 4e76438..d541cac 100644 --- a/Log/Logger.js +++ b/Log/Logger.js @@ -1,3 +1,6 @@ +import { LogLevel } from './LogLevel.js'; +import { Request } from '../Message/Request/Request.js'; + /** * Logger class. * @@ -6,341 +9,334 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - /** @namespace jsOMS.Log */ - jsOMS.Autoloader.defineNamespace('jsOMS.Log'); +export class Logger { + /** + * @constructor + * + * @param {boolean} verbose Verbose logging + * @param {boolean} ui Ui logging + * @param {boolean} remote Remote logging + * + * @since 1.0.0 + */ + constructor (verbose = true, ui = true, remote = false) + { + this.verbose = verbose; + this.ui = ui; + this.remote = remote; + }; - jsOMS.Log.Logger = class { - /** - * @constructor - * - * @param {boolean} verbose Verbose logging - * @param {boolean} ui Ui logging - * @param {boolean} remote Remote logging - * - * @since 1.0.0 - */ - constructor (verbose = true, ui = true, remote = false) - { - this.verbose = verbose; - this.ui = ui; - this.remote = remote; - }; + /** + * Get logging instance + * + * @param {boolean} [verbose] Verbose logging + * @param {boolean} [ui] Ui logging + * @param {boolean} [remote] Remote logging + * + * @return {Object} + * + * @since 1.0.0 + */ + static getInstance (verbose = true, ui = true, remote = false) + { + if(!Logger.instance) { + Logger.instance = new Logger(verbose, ui, remote); + } - /** - * Get logging instance - * - * @param {boolean} [verbose] Verbose logging - * @param {boolean} [ui] Ui logging - * @param {boolean} [remote] Remote logging - * - * @return {Object} - * - * @since 1.0.0 - */ - static getInstance (verbose = true, ui = true, remote = false) - { - if(!jsOMS.Log.Logger.instance) { - jsOMS.Log.Logger.instance = new jsOMS.Log.Logger(verbose, ui, remote); + return Logger.instance; + }; + + /** + * Interpolate message + * + * @param {string} message Message structure + * @param {Object} [context] Context to put into message + * @param {string} [level] Log level + * + * @return {string} + * + * @since 1.0.0 + */ + interpolate (message, context, level) + { + message = typeof message === 'undefined' ? Logger.MSG_FULL : message; + + for (let replace in context) { + if (context.hasOwnProperty(replace) && typeof message === 'string') { + message = message.replace('{' + replace + '}', context[replace]); } + } - return jsOMS.Log.Logger.instance; - }; + return (typeof message) !== 'string' ? JSON.stringify(message) : message; + }; - /** - * Interpolate message - * - * @param {string} message Message structure - * @param {Object} [context] Context to put into message - * @param {string} [level] Log level - * - * @return {string} - * - * @since 1.0.0 - */ - interpolate (message, context, level) + /** + * Create context + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * @param {string} level Log level + * + * @return {Object} + * + * @since 1.0.0 + */ + createContext (message, context, level) + { + context.datetime = (new Date()).toISOString(); + context.version = '1.0.0'; + context.os = Request.getOS(); + context.browser = Request.getBrowser(); + context.path = window.location.href; + context.level = level; + context.message = message; + + return context; + }; + + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * @param {string} level Log level + * + * @return {void} + * + * @since 1.0.0 + */ + write (message, context, level) + { + context = this.createContext(message, context, level); + + if (this.verbose) { + this.writeVerbose(message, context, level); + } + + if (this.ui) { + // todo: fill log box, set class and initiate animation + } + + if (this.remote) { + this.writeRemote(message, context, level); + } + }; + + /** + * Create local log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * @param {string} level Log level + * + * @return {void} + * + * @since 1.0.0 + */ + writeVerbose (message, context, level) + { + let color = '000'; + + switch (level) { + case 'info': + case 'notice': + case 'log': + color = '000'; + break; + case 'debug': + color = '289E39'; + break; + case 'warning': + case 'alert': + color = 'FFA600'; + break; + case 'error': + case 'critical': + case 'emergency': + color = 'CF304A'; + break; + default: + } + + console.log('%c' + this.interpolate(message, context, level), 'color: #' + color); + }; + + /** + * Create remote log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * @param {string} level Log level + * + * @return {void} + * + * @since 1.0.0 + */ + writeRemote (message, context, level) + { + let request = new Request(); + request.setData(context); + request.setType(jsOMS.Message.Response.Response.ResponseType.JSON); + request.setUri('/{/lang}/api/log'); + request.setMethod(Request.RequestMethod.POST); + request.setRequestHeader('Content-Type', 'application/json'); + request.setSuccess(function (xhr) { - message = typeof message === 'undefined' ? jsOMS.Log.Logger.MSG_FULL : message; + }); + request.send(); + }; - for (let replace in context) { - if (context.hasOwnProperty(replace) && typeof message === 'string') { - message = message.replace('{' + replace + '}', context[replace]); - } - } + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + emergency (message, context = {}) + { + this.write(message, context, LogLevel.EMERGENCY); + }; - return (typeof message) !== 'string' ? JSON.stringify(message) : message; - }; + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + alert (message, context = {}) + { + this.write(message, context, LogLevel.ALERT); + }; - /** - * Create context - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * @param {string} level Log level - * - * @return {Object} - * - * @since 1.0.0 - */ - createContext (message, context, level) - { - context.datetime = (new Date()).toISOString(); - context.version = '1.0.0'; - context.os = jsOMS.Message.Request.Request.getOS(); - context.browser = jsOMS.Message.Request.Request.getBrowser(); - context.path = window.location.href; - context.level = level; - context.message = message; + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + critical (message, context = {}) + { + this.write(message, context, LogLevel.CRITICAL); + }; - return context; - }; + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + error (message, context = {}) + { + this.write(message, context, LogLevel.ERROR); + }; - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * @param {string} level Log level - * - * @return {void} - * - * @since 1.0.0 - */ - write (message, context, level) - { - context = this.createContext(message, context, level); + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + warning (message, context = {}) + { + this.write(message, context, LogLevel.WARNING); + }; - if (this.verbose) { - this.writeVerbose(message, context, level); - } + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + notice (message, context = {}) + { + this.write(message, context, LogLevel.NOTICE); + }; - if (this.ui) { - // todo: fill log box, set class and initiate animation - } + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + info (message, context = {}) + { + this.write(message, context, LogLevel.INFO); + }; - if (this.remote) { - this.writeRemote(message, context, level); - } - }; + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + debug (message, context = {}) + { + this.write(message, context, LogLevel.DEBUG); + }; - /** - * Create local log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * @param {string} level Log level - * - * @return {void} - * - * @since 1.0.0 - */ - writeVerbose (message, context, level) - { - let color = '000'; + /** + * Create log message + * + * @param {string} level Log level + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + log (level, message, context = {}) + { + this.write(message, context, level); + }; - switch (level) { - case 'info': - case 'notice': - case 'log': - color = '000'; - break; - case 'debug': - color = '289E39'; - break; - case 'warning': - case 'alert': - color = 'FFA600'; - break; - case 'error': - case 'critical': - case 'emergency': - color = 'CF304A'; - break; - default: - } + /** + * Create log message + * + * @param {string} message Message to display + * @param {Object} [context] Context to put into message + * + * @return {void} + * + * @since 1.0.0 + */ + console (message, context = {}) + { + this.writeVerbose(message, context, LogLevel.INFO); + }; +} - console.log('%c' + this.interpolate(message, context, level), 'color: #' + color); - }; - - /** - * Create remote log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * @param {string} level Log level - * - * @return {void} - * - * @since 1.0.0 - */ - writeRemote (message, context, level) - { - let request = new jsOMS.Message.Request.Request(); - request.setData(context); - request.setType(jsOMS.Message.Response.Response.ResponseType.JSON); - request.setUri('/{/lang}/api/log'); - request.setMethod(jsOMS.Message.Request.Request.RequestMethod.POST); - request.setRequestHeader('Content-Type', 'application/json'); - request.setSuccess(function (xhr) - { - }); - request.send(); - }; - - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - emergency (message, context = {}) - { - this.write(message, context, jsOMS.Log.LogLevel.EMERGENCY); - }; - - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - alert (message, context = {}) - { - this.write(message, context, jsOMS.Log.LogLevel.ALERT); - }; - - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - critical (message, context = {}) - { - this.write(message, context, jsOMS.Log.LogLevel.CRITICAL); - }; - - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - error (message, context = {}) - { - this.write(message, context, jsOMS.Log.LogLevel.ERROR); - }; - - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - warning (message, context = {}) - { - this.write(message, context, jsOMS.Log.LogLevel.WARNING); - }; - - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - notice (message, context = {}) - { - this.write(message, context, jsOMS.Log.LogLevel.NOTICE); - }; - - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - info (message, context = {}) - { - this.write(message, context, jsOMS.Log.LogLevel.INFO); - }; - - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - debug (message, context = {}) - { - this.write(message, context, jsOMS.Log.LogLevel.DEBUG); - }; - - /** - * Create log message - * - * @param {string} level Log level - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - log (level, message, context = {}) - { - this.write(message, context, level); - }; - - /** - * Create log message - * - * @param {string} message Message to display - * @param {Object} [context] Context to put into message - * - * @return {void} - * - * @since 1.0.0 - */ - console (message, context = {}) - { - this.writeVerbose(message, context, jsOMS.Log.LogLevel.INFO); - }; - } - - jsOMS.Log.Logger.instance = null; - jsOMS.Log.Logger.MSG_FULL = '{datetime}; {level}; {version}; {os}; {browser}; {path}; {message}'; -}(window.jsOMS = window.jsOMS || {})); +Logger.instance = null; +Logger.MSG_FULL = '{datetime}; {level}; {version}; {os}; {browser}; {path}; {message}'; diff --git a/Message/Notification/App/AppNotification.js b/Message/Notification/App/AppNotification.js index faaf222..fe049b3 100644 --- a/Message/Notification/App/AppNotification.js +++ b/Message/Notification/App/AppNotification.js @@ -6,66 +6,58 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class AppNotification { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + this.status = 0; + }; - /** @namespace jsOMS.Message.Notification.App */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Notification.App'); + /** + * Set notification status. + * + * @param {int} status Notification status + * + * @return {void} + * + * @since 1.0.0 + */ + setStatus (status) + { + this.status = status; + }; - jsOMS.Message.Notification.App.AppNotification = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () + /** + * Create notification + * + * @param {Object} msg Notification + * + * @return {void} + * + * @since 1.0.0 + */ + send (msg) + { + const tpl = document.getElementById('app-message-tpl'); + + if (tpl === null) { + return; + } + + let output = document.importNode(tpl.content, true); + output.querySelector('.log-msg').classList.add('log-msg-status-' + msg.status); + output.querySelector('.log-msg-title').innerHTML = msg.title; + output.querySelector('.log-msg-content').innerHTML = msg.message; + + tpl.parentNode.appendChild(output); + + setTimeout(function () { - this.status = 0; - }; - - /** - * Set notification status. - * - * @param {int} status Notification status - * - * @return {void} - * - * @since 1.0.0 - */ - setStatus (status) - { - this.status = status; - }; - - /** - * Create notification - * - * @param {Object} msg Notification - * - * @return {void} - * - * @since 1.0.0 - */ - send (msg) - { - const tpl = document.getElementById('app-message-tpl'); - - if (tpl === null) { - return; - } - - let output = document.importNode(tpl.content, true); - output.querySelector('.log-msg').classList.add('log-msg-status-' + msg.status); - output.querySelector('.log-msg-title').innerHTML = msg.title; - output.querySelector('.log-msg-content').innerHTML = msg.message; - - tpl.parentNode.appendChild(output); - - setTimeout(function () - { - document.getElementsByClassName('log-msg')[0].remove(); - }, 3000); - }; - } -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file + document.getElementsByClassName('log-msg')[0].remove(); + }, 3000); + }; +}; \ No newline at end of file diff --git a/Message/Notification/Browser/BrowserNotification.js b/Message/Notification/Browser/BrowserNotification.js index 5515324..fd28cf7 100644 --- a/Message/Notification/Browser/BrowserNotification.js +++ b/Message/Notification/Browser/BrowserNotification.js @@ -6,75 +6,67 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class BrowserNotification { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor() + { + this.status = 0; + }; - /** @namespace jsOMS.Message.Notification.Browser */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Notification.Browser'); + /** + * Set notification status. + * + * @param {int} status Notification status + * + * @return {void} + * + * @since 1.0.0 + */ + setStatus (status) + { + this.status = status; + }; - jsOMS.Message.Notification.Browser.BrowserNotification = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor() - { - this.status = 0; - }; + /** + * Ask for browser permission to create notifications + * + * @return {void} + * + * @since 1.0.0 + */ + requestPermission () + { + const self = this; - /** - * Set notification status. - * - * @param {int} status Notification status - * - * @return {void} - * - * @since 1.0.0 - */ - setStatus (status) - { - this.status = status; - }; + /** global: Notification */ + if(Notification.permission !== 'granted' && Notification.permission !== 'denied') { + Notification.requestPermission(function(permission) { + if(permission === 'granted') { + let msg = new jsOMS.Message.Notification.NotificationMessage(); - /** - * Ask for browser permission to create notifications - * - * @return {void} - * - * @since 1.0.0 - */ - requestPermission () - { - const self = this; + self.send(msg); + } + }); + } + }; - /** global: Notification */ - if(Notification.permission !== 'granted' && Notification.permission !== 'denied') { - Notification.requestPermission(function(permission) { - if(permission === 'granted') { - let msg = new jsOMS.Message.Notification.NotificationMessage(); - - self.send(msg); - } - }); - } - }; - - /** - * Create notification - * - * @param {Object} msg Notification - * - * @return {void} - * - * @since 1.0.0 - */ - send (msg) - { - // todo: implement - /** global: Notification */ - let n = new Notification(/* ... */); - }; - } -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file + /** + * Create notification + * + * @param {Object} msg Notification + * + * @return {void} + * + * @since 1.0.0 + */ + send (msg) + { + // todo: implement + /** global: Notification */ + let n = new Notification(/* ... */); + }; +}; \ No newline at end of file diff --git a/Message/Notification/NotificationLevel.js b/Message/Notification/NotificationLevel.js index 2a23568..750d3cf 100644 --- a/Message/Notification/NotificationLevel.js +++ b/Message/Notification/NotificationLevel.js @@ -6,16 +6,9 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) { - "use strict"; - - /** @namespace jsOMS.Message.Notification */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Notification'); - - jsOMS.Message.Notification.NotificationLevel = Object.freeze({ - OK: 'ok', - INFO: 'info', - WARNING: 'warning', - ERROR: 'error' - }); -}(window.jsOMS = window.jsOMS || {})); +export const NotificationLevel = Object.freeze({ + OK: 'ok', + INFO: 'info', + WARNING: 'warning', + ERROR: 'error' +}); diff --git a/Message/Notification/NotificationManager.js b/Message/Notification/NotificationManager.js index 375c487..45ad1fa 100644 --- a/Message/Notification/NotificationManager.js +++ b/Message/Notification/NotificationManager.js @@ -1,3 +1,7 @@ +import { AppNotification } from '../../../jsOMS/Message/Notification/App/AppNotification.js'; +import { BrowserNotification } from '../../../jsOMS/Message/Notification/Browser/BrowserNotification.js'; +import { NotificationType } from '../../../jsOMS/Message/Notification/NotificationType.js'; + /** * Notification manager. * @@ -6,66 +10,58 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class NotificationManager { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor() + { + this.appNotifier = new AppNotification(); + this.browserNotifier = new BrowserNotification(); + }; - /** @namespace jsOMS.Message.Notification */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Notification'); + /** + * Create notification. + * + * @param {Object} message Message object + * @param {int} type Notification type + * + * @return {void} + * + * @since 1.0.0 + */ + send (message, type) + { + if (NotificationType.APP_NOTIFICATION === type) { + this.appNotifier.send(message); + } else { + this.browserNotifier.send(message); + } + }; - jsOMS.Message.Notification.NotificationManager = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor() - { - this.appNotifier = new jsOMS.Message.Notification.App.AppNotification(); - this.browserNotifier = new jsOMS.Message.Notification.Browser.BrowserNotification(); - }; + /** + * Get the app notification manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getAppNotifier () + { + return this.appNotifier; + }; - /** - * Create notification. - * - * @param {Object} message Message object - * @param {int} type Notification type - * - * @return {void} - * - * @since 1.0.0 - */ - send (message, type) - { - if (jsOMS.Message.Notification.NotificationType.APP_NOTIFICATION === type) { - this.appNotifier.send(message); - } else { - this.browserNotifier.send(message); - } - }; - - /** - * Get the app notification manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getAppNotifier () - { - return this.appNotifier; - }; - - /** - * Get the browser notification manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getBrowserNotifier () - { - return this.browserNotifier; - }; - } -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file + /** + * Get the browser notification manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getBrowserNotifier () + { + return this.browserNotifier; + }; +}; \ No newline at end of file diff --git a/Message/Notification/NotificationMessage.js b/Message/Notification/NotificationMessage.js index ebcd1d7..40a72f7 100644 --- a/Message/Notification/NotificationMessage.js +++ b/Message/Notification/NotificationMessage.js @@ -6,27 +6,20 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) { - "use strict"; - - /** @namespace jsOMS.Message.Notification.App */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Notification'); - - jsOMS.Message.Notification.NotificationMessage = class { - /** - * @constructor - * - * @param {string} status Message status - * @param {string} title Message title - * @param {string} message Message content - * - * @since 1.0.0 - */ - constructor(status, title, message) - { - this.status = status; - this.title = title; - this.message = message; - }; - } -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file +export class NotificationMessage { + /** + * @constructor + * + * @param {string} status Message status + * @param {string} title Message title + * @param {string} message Message content + * + * @since 1.0.0 + */ + constructor(status, title, message) + { + this.status = status; + this.title = title; + this.message = message; + }; +}; \ No newline at end of file diff --git a/Message/Notification/NotificationType.js b/Message/Notification/NotificationType.js index ee4583f..2f89416 100644 --- a/Message/Notification/NotificationType.js +++ b/Message/Notification/NotificationType.js @@ -6,15 +6,7 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.Message.Notification */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Notification'); - - jsOMS.Message.Notification.NotificationType = Object.freeze({ - APP_NOTIFICATION: 1, - BROWSER_NOTIFICATION: 2 - }); -}(window.jsOMS = window.jsOMS || {})); +export const NotificationType = Object.freeze({ + APP_NOTIFICATION: 1, + BROWSER_NOTIFICATION: 2 +}); diff --git a/Message/Request/BrowserType.js b/Message/Request/BrowserType.js index 1320b7e..3b53b08 100644 --- a/Message/Request/BrowserType.js +++ b/Message/Request/BrowserType.js @@ -6,21 +6,13 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.Message.Request */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Request'); - - jsOMS.Message.Request.BrowserType = Object.freeze({ - OPERA: 'opera', - FIREFOX: 'firefox', - SAFARI: 'safari', - IE: 'msie', - EDGE: 'edge', - CHROME: 'chrome', - BLINK: 'blink', - UNKNOWN: 'unknown' - }); -}(window.jsOMS = window.jsOMS || {})); +export const BrowserType = Object.freeze({ + OPERA: 'opera', + FIREFOX: 'firefox', + SAFARI: 'safari', + IE: 'msie', + EDGE: 'edge', + CHROME: 'chrome', + BLINK: 'blink', + UNKNOWN: 'unknown' +}); diff --git a/Message/Request/OSType.js b/Message/Request/OSType.js index cd71e86..a24a543 100644 --- a/Message/Request/OSType.js +++ b/Message/Request/OSType.js @@ -6,38 +6,30 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.Message.Request */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Request'); - - jsOMS.Message.Request.OSType = Object.freeze({ - WINDOWS_10: 'windows nt 10.0', /* Windows 10 */ - WINDOWS_81: 'windows nt 6.3', /* Windows 8.1 */ - WINDOWS_8: 'windows nt 6.2', /* Windows 8 */ - WINDOWS_7: 'windows nt 6.1', /* Windows 7 */ - WINDOWS_VISTA: 'windows nt 6.0', /* Windows Vista */ - WINDOWS_SERVER: 'windows nt 5.2', /* Windows Server 2003/XP x64 */ - WINDOWS_XP: 'windows nt 5.1', /* Windows XP */ - WINDOWS_XP_2: 'windows xp', /* Windows XP */ - WINDOWS_2000: 'windows nt 5.0', /* Windows 2000 */ - WINDOWS_ME: 'windows me', /* Windows ME */ - WINDOWS_98: 'win98', /* Windows 98 */ - WINDOWS_95: 'win95', /* Windows 95 */ - WINDOWS_311: 'win16', /* Windows 3.11 */ - MAC_OS_X: 'macintosh', /* Mac OS X */ - MAC_OS_X_2: 'mac os x', /* Mac OS X */ - MAC_OS_9: 'mac_powerpc', /* Mac OS 9 */ - LINUX : 'linux', /* Linux */ - UBUNTU: 'ubuntu', /* Ubuntu */ - IPHONE: 'iphone', /* IPhone */ - IPOD: 'ipod', /* IPod */ - IPAD: 'ipad', /* IPad */ - ANDROID: 'android', /* Android */ - BLACKBERRY: 'blackberry', /* Blackberry */ - MOBILE: 'webos', /* Mobile */ - UNKNOWN: 'UNKNOWN' /* Unknown */ - }); -}(window.jsOMS = window.jsOMS || {})); +export const OSType = Object.freeze({ + WINDOWS_10: 'windows nt 10.0', /* Windows 10 */ + WINDOWS_81: 'windows nt 6.3', /* Windows 8.1 */ + WINDOWS_8: 'windows nt 6.2', /* Windows 8 */ + WINDOWS_7: 'windows nt 6.1', /* Windows 7 */ + WINDOWS_VISTA: 'windows nt 6.0', /* Windows Vista */ + WINDOWS_SERVER: 'windows nt 5.2', /* Windows Server 2003/XP x64 */ + WINDOWS_XP: 'windows nt 5.1', /* Windows XP */ + WINDOWS_XP_2: 'windows xp', /* Windows XP */ + WINDOWS_2000: 'windows nt 5.0', /* Windows 2000 */ + WINDOWS_ME: 'windows me', /* Windows ME */ + WINDOWS_98: 'win98', /* Windows 98 */ + WINDOWS_95: 'win95', /* Windows 95 */ + WINDOWS_311: 'win16', /* Windows 3.11 */ + MAC_OS_X: 'macintosh', /* Mac OS X */ + MAC_OS_X_2: 'mac os x', /* Mac OS X */ + MAC_OS_9: 'mac_powerpc', /* Mac OS 9 */ + LINUX : 'linux', /* Linux */ + UBUNTU: 'ubuntu', /* Ubuntu */ + IPHONE: 'iphone', /* IPhone */ + IPOD: 'ipod', /* IPod */ + IPAD: 'ipad', /* IPad */ + ANDROID: 'android', /* Android */ + BLACKBERRY: 'blackberry', /* Blackberry */ + MOBILE: 'webos', /* Mobile */ + UNKNOWN: 'UNKNOWN' /* Unknown */ +}); diff --git a/Message/Request/Request.js b/Message/Request/Request.js index 36c02bb..b7ba53e 100644 --- a/Message/Request/Request.js +++ b/Message/Request/Request.js @@ -1,3 +1,10 @@ +import { RequestMethod } from './RequestMethod.js' +import { RequestType } from './RequestType.js' +import { BrowserType } from './BrowserType.js' +import { OSType } from './OSType.js' +import { UriFactory } from '../../Uri/UriFactory.js' +import { Logger } from '../../Log/Logger.js' + /** * Request class. * @@ -6,382 +13,374 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class Request { + /** + * @constructor + * + * @param {string} uri Request uri + * @param {string} method Request method/verb + * @param {string} type Request content type + * + * @since 1.0.0 + */ + constructor (uri = null, method, type) + { + this.uri = uri; + this.method = typeof method !== 'undefined' ? method : RequestMethod.GET; + this.requestHeader = []; + this.result = {}; + this.type = typeof type !== 'undefined' ? type : RequestType.JSON; + this.data = {}; - /** @namespace jsOMS.Message.Request */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Request'); + this.requestHeader['Content-Type'] = this.setContentTypeBasedOnType(this.type); - jsOMS.Message.Request.Request = class { - /** - * @constructor - * - * @param {string} uri Request uri - * @param {string} method Request method/verb - * @param {string} type Request content type - * - * @since 1.0.0 - */ - constructor (uri = null, method, type) + this.result[0] = function() { - this.uri = uri; - this.method = typeof method !== 'undefined' ? method : jsOMS.Message.Request.RequestMethod.GET; - this.requestHeader = []; - this.result = {}; - this.type = typeof type !== 'undefined' ? type : jsOMS.Message.Request.RequestType.JSON; - this.data = {}; - - this.requestHeader['Content-Type'] = this.setContentTypeBasedOnType(this.type); - - this.result[0] = function() - { - jsOMS.Log.Logger.instance.info('Unhandled response'); - }; - - /** global: XMLHttpRequest */ - this.xhr = new XMLHttpRequest(); + Logger.instance.info('Unhandled response'); }; - /** - * Defines the request content type based on the type - * - * @return {string} - * - * @since 1.0.0 - */ - setContentTypeBasedOnType(type) + /** global: XMLHttpRequest */ + this.xhr = new XMLHttpRequest(); + }; + + /** + * Defines the request content type based on the type + * + * @return {string} + * + * @since 1.0.0 + */ + setContentTypeBasedOnType(type) + { + switch(type) { + case RequestType.JSON: + return 'application/json'; + case RequestType.URL_ENCODE: + return 'application/x-www-form-urlencoded'; + case RequestType.FILE: + return ''; + default: + return 'text/plain'; + } + }; + + /** + * Get browser. + * + * @return {string} + * + * @since 1.0.0 + */ + static getBrowser() + { + /** global: InstallTrigger */ + /** global: navigator */ + if ((!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) { + return BrowserType.OPERA; + } else if (typeof InstallTrigger !== 'undefined') { + return BrowserType.FIREFOX; + } else if (Object.toString.call(window.HTMLElement).indexOf('Constructor') > 0) { + return BrowserType.SAFARI; + } else if (/*@cc_on!@*/false || !!document.documentMode) { + return BrowserType.IE; + } else if (!!window.StyleMedia) { + return BrowserType.EDGE; + } else if (!!window.chrome && !!window.chrome.webstore) { + return BrowserType.CHROME; + } else if (((typeof isChrome !== 'undefined' && isChrome) + || (typeof isOpera !== 'undefined' && isOpera)) + && !!window.CSS + ) { + return BrowserType.BLINK; + } + + return BrowserType.UNKNOWN; + }; + + /** + * Get os. + * + * @return {string} + * + * @since 1.0.0 + */ + static getOS() + { + for (let os in OSType) { + if (OSType.hasOwnProperty(os)) { + /** global: navigator */ + if (navigator.appVersion.toLowerCase().indexOf(OSType[os]) !== -1) { + return OSType[os]; + } + } + } + + return OSType.UNKNOWN; + }; + + /** + * Set request method. + * + * EnumRequestMethod + * + * @param {string} method Method type + * + * @return {void} + * + * @since 1.0.0 + */ + setMethod(method) + { + this.method = method; + }; + + /** + * Get request method. + * + * EnumRequestMethod + * + * @return {string} + * + * @since 1.0.0 + */ + getMethod() + { + return this.method; + }; + + /** + * Set response type. + * + * EnumResponseType + * + * @param {string} type Method type + * + * @return {void} + * + * @since 1.0.0 + */ + setResponseType(type) + { + this.xhr.responseType = type; + }; + + /** + * Get response type. + * + * EnumResponseType + * + * @return {string} + * + * @since 1.0.0 + */ + getResponseType() + { + return this.responseType; + }; + + /** + * Set request header. + * + * @param {string} type Request type + * @param {string} header Request header + * + * @return {void} + * + * @since 1.0.0 + */ + setRequestHeader(type, header) + { + this.requestHeader[type] = header; + }; + + /** + * Get request header. + * + * @return {Array} + * + * @since 1.0.0 + */ + getRequestHeader() + { + return this.requestHeader; + }; + + /** + * Set request uri. + * + * @param {string} uri Request uri + * + * @return {void} + * + * @since 1.0.0 + */ + setUri(uri) + { + this.uri = uri; + }; + + /** + * Get request uri. + * + * @return {string} + * + * @since 1.0.0 + */ + getUri() + { + return this.uri; + }; + + /** + * Set success callback. + * + * @param {requestCallback} callback - Success callback + * + * @return {void} + * + * @since 1.0.0 + */ + setSuccess(callback) + { + this.result[200] = callback; + }; + + /** + * Set result callback. + * + * @param {int} status Http response status + * @param {function} callback Callback + * + * @return {void} + * + * @since 1.0.0 + */ + setResultCallback(status, callback) + { + this.result[status] = callback; + }; + + /** + * Set request data. + * + * @param {Array} data Request data + * + * @return {void} + * + * @since 1.0.0 + */ + setData(data) + { + this.data = data; + }; + + /** + * Get request data. + * + * @return {Array} + * + * @since 1.0.0 + */ + getData() + { + return this.data; + }; + + /** + * Set request type. + * + * EnumRequestType + * + * @param {string} type Method type + * + * @return {void} + * + * @since 1.0.0 + */ + setType(type) + { + this.type = type; + this.requestHeader['Content-Type'] = this.setContentTypeBasedOnType(this.type); + }; + + /** + * Get request type. + * + * EnumRequestType + * + * @return {string} + * + * @since 1.0.0 + */ + getType() + { + return this.type; + }; + + /** + * Create query from object. + * + * @return {string} + * + * @since 1.0.0 + */ + queryfy(obj) + { + const str = []; + for (let p in obj) { + if (obj.hasOwnProperty(p)) { + str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); + } + } + + return str.join("&"); + }; + + /** + * Get request data. + * + * @return {Array} + * + * @since 1.0.0 + */ + send() + { + const self = this; + + if (this.xhr.readyState !== 1) { + this.xhr.open(this.method, UriFactory.build(this.uri)); + + for (let p in this.requestHeader) { + if (this.requestHeader.hasOwnProperty(p) && this.requestHeader[p] !== '') { + this.xhr.setRequestHeader(p, this.requestHeader[p]); + } + } + } + + console.log(this.xhr); + + this.xhr.onreadystatechange = function() { - switch(type) { - case jsOMS.Message.Request.RequestType.JSON: - return 'application/json'; - case jsOMS.Message.Request.RequestType.URL_ENCODE: - return 'application/x-www-form-urlencoded'; - case jsOMS.Message.Request.RequestType.FILE: - return ''; + switch (self.xhr.readyState) { + case 4: + if (typeof self.result[self.xhr.status] === 'undefined') { + self.result[0](self.xhr); + } else { + self.result[self.xhr.status](self.xhr); + } + break; default: - return 'text/plain'; } }; - /** - * Get browser. - * - * @return {string} - * - * @since 1.0.0 - */ - static getBrowser() - { - /** global: InstallTrigger */ - /** global: navigator */ - if ((!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) { - return jsOMS.Message.Request.BrowserType.OPERA; - } else if (typeof InstallTrigger !== 'undefined') { - return jsOMS.Message.Request.BrowserType.FIREFOX; - } else if (Object.toString.call(window.HTMLElement).indexOf('Constructor') > 0) { - return jsOMS.Message.Request.BrowserType.SAFARI; - } else if (/*@cc_on!@*/false || !!document.documentMode) { - return jsOMS.Message.Request.BrowserType.IE; - } else if (!!window.StyleMedia) { - return jsOMS.Message.Request.BrowserType.EDGE; - } else if (!!window.chrome && !!window.chrome.webstore) { - return jsOMS.Message.Request.BrowserType.CHROME; - } else if (((typeof isChrome !== 'undefined' && isChrome) - || (typeof isOpera !== 'undefined' && isOpera)) - && !!window.CSS - ) { - return jsOMS.Message.Request.BrowserType.BLINK; - } - - return jsOMS.Message.Request.BrowserType.UNKNOWN; - }; - - /** - * Get os. - * - * @return {string} - * - * @since 1.0.0 - */ - static getOS() - { - for (let os in jsOMS.Message.Request.OSType) { - if (jsOMS.Message.Request.OSType.hasOwnProperty(os)) { - /** global: navigator */ - if (navigator.appVersion.toLowerCase().indexOf(jsOMS.Message.Request.OSType[os]) !== -1) { - return jsOMS.Message.Request.OSType[os]; - } - } - } - - return jsOMS.Message.Request.OSType.UNKNOWN; - }; - - /** - * Set request method. - * - * EnumRequestMethod - * - * @param {string} method Method type - * - * @return {void} - * - * @since 1.0.0 - */ - setMethod(method) - { - this.method = method; - }; - - /** - * Get request method. - * - * EnumRequestMethod - * - * @return {string} - * - * @since 1.0.0 - */ - getMethod() - { - return this.method; - }; - - /** - * Set response type. - * - * EnumResponseType - * - * @param {string} type Method type - * - * @return {void} - * - * @since 1.0.0 - */ - setResponseType(type) - { - this.xhr.responseType = type; - }; - - /** - * Get response type. - * - * EnumResponseType - * - * @return {string} - * - * @since 1.0.0 - */ - getResponseType() - { - return this.responseType; - }; - - /** - * Set request header. - * - * @param {string} type Request type - * @param {string} header Request header - * - * @return {void} - * - * @since 1.0.0 - */ - setRequestHeader(type, header) - { - this.requestHeader[type] = header; - }; - - /** - * Get request header. - * - * @return {Array} - * - * @since 1.0.0 - */ - getRequestHeader() - { - return this.requestHeader; - }; - - /** - * Set request uri. - * - * @param {string} uri Request uri - * - * @return {void} - * - * @since 1.0.0 - */ - setUri(uri) - { - this.uri = uri; - }; - - /** - * Get request uri. - * - * @return {string} - * - * @since 1.0.0 - */ - getUri() - { - return this.uri; - }; - - /** - * Set success callback. - * - * @param {requestCallback} callback - Success callback - * - * @return {void} - * - * @since 1.0.0 - */ - setSuccess(callback) - { - this.result[200] = callback; - }; - - /** - * Set result callback. - * - * @param {int} status Http response status - * @param {function} callback Callback - * - * @return {void} - * - * @since 1.0.0 - */ - setResultCallback(status, callback) - { - this.result[status] = callback; - }; - - /** - * Set request data. - * - * @param {Array} data Request data - * - * @return {void} - * - * @since 1.0.0 - */ - setData(data) - { - this.data = data; - }; - - /** - * Get request data. - * - * @return {Array} - * - * @since 1.0.0 - */ - getData() - { - return this.data; - }; - - /** - * Set request type. - * - * EnumRequestType - * - * @param {string} type Method type - * - * @return {void} - * - * @since 1.0.0 - */ - setType(type) - { - this.type = type; - this.requestHeader['Content-Type'] = this.setContentTypeBasedOnType(this.type); - }; - - /** - * Get request type. - * - * EnumRequestType - * - * @return {string} - * - * @since 1.0.0 - */ - getType() - { - return this.type; - }; - - /** - * Create query from object. - * - * @return {string} - * - * @since 1.0.0 - */ - queryfy(obj) - { - const str = []; - for (let p in obj) { - if (obj.hasOwnProperty(p)) { - str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); - } - } - - return str.join("&"); - }; - - /** - * Get request data. - * - * @return {Array} - * - * @since 1.0.0 - */ - send() - { - const self = this; - - if (this.xhr.readyState !== 1) { - this.xhr.open(this.method, jsOMS.Uri.UriFactory.build(this.uri)); - - for (let p in this.requestHeader) { - if (this.requestHeader.hasOwnProperty(p) && this.requestHeader[p] !== '') { - this.xhr.setRequestHeader(p, this.requestHeader[p]); - } - } - } - - console.log(this.xhr); - - this.xhr.onreadystatechange = function() - { - switch (self.xhr.readyState) { - case 4: - if (typeof self.result[self.xhr.status] === 'undefined') { - self.result[0](self.xhr); - } else { - self.result[self.xhr.status](self.xhr); - } - break; - default: - } - }; - - if (this.type === jsOMS.Message.Request.RequestType.JSON) { - this.xhr.send(JSON.stringify(this.data)); - } else if (this.type === jsOMS.Message.Request.RequestType.RAW - || this.type === jsOMS.Message.Request.RequestType.FILE - ) { - this.xhr.send(this.data); - } else if (this.type === jsOMS.Message.Request.RequestType.URL_ENCODE) { - this.xhr.send(this.queryfy(this.data)); - } - }; - } -}(window.jsOMS = window.jsOMS || {})); + if (this.type === RequestType.JSON) { + this.xhr.send(JSON.stringify(this.data)); + } else if (this.type === RequestType.RAW + || this.type === RequestType.FILE + ) { + this.xhr.send(this.data); + } else if (this.type === RequestType.URL_ENCODE) { + this.xhr.send(this.queryfy(this.data)); + } + }; +}; diff --git a/Message/Request/RequestMethod.js b/Message/Request/RequestMethod.js index 521b495..fad7e42 100644 --- a/Message/Request/RequestMethod.js +++ b/Message/Request/RequestMethod.js @@ -6,18 +6,10 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.Message.Request */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Request'); - - jsOMS.Message.Request.RequestMethod = Object.freeze({ - POST: 'POST', - GET: 'GET', - PUT: 'PUT', - DELETE: 'DELETE', - HEAD: 'HEAD' - }); -}(window.jsOMS = window.jsOMS || {})); +export const RequestMethod = Object.freeze({ + POST: 'POST', + GET: 'GET', + PUT: 'PUT', + DELETE: 'DELETE', + HEAD: 'HEAD' +}); diff --git a/Message/Request/RequestType.js b/Message/Request/RequestType.js index 6b6efe1..f8e5bf7 100644 --- a/Message/Request/RequestType.js +++ b/Message/Request/RequestType.js @@ -6,17 +6,9 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.Message.Request */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Request'); - - jsOMS.Message.Request.RequestType = Object.freeze({ - JSON: 'json', - RAW: 'raw', - FILE: 'file', - URL_ENCODE: 'url' - }); -}(window.jsOMS = window.jsOMS || {})); +export const RequestType = Object.freeze({ + JSON: 'json', + RAW: 'raw', + FILE: 'file', + URL_ENCODE: 'url' +}); diff --git a/Message/Response/Response.js b/Message/Response/Response.js index de87c59..9127635 100644 --- a/Message/Response/Response.js +++ b/Message/Response/Response.js @@ -8,50 +8,42 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class Response { + /** + * @constructor + * + * @param {mixed} data Response data + * + * @since 1.0.0 + */ + constructor (data) + { + this.responses = data; + }; - /** @namespace jsOMS.Message.Response */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Response'); + /** + * Get response by id. + * + * @param {string} id Response id + * + * @return {mixed} + * + * @since 1.0.0 + */ + get (id) + { + return this.responses[id]; + }; - jsOMS.Message.Response.Response = class { - /** - * @constructor - * - * @param {mixed} data Response data - * - * @since 1.0.0 - */ - constructor (data) - { - this.responses = data; - }; - - /** - * Get response by id. - * - * @param {string} id Response id - * - * @return {mixed} - * - * @since 1.0.0 - */ - get (id) - { - return this.responses[id]; - }; - - /** - * Count the amount of responses. - * - * @return {int} - * - * @since 1.0.0 - */ - count () - { - return this.responses.length; - }; - } -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file + /** + * Count the amount of responses. + * + * @return {int} + * + * @since 1.0.0 + */ + count () + { + return this.responses.length; + }; +}; \ No newline at end of file diff --git a/Message/Response/ResponseManager.js b/Message/Response/ResponseManager.js index 0390efa..85e5803 100644 --- a/Message/Response/ResponseManager.js +++ b/Message/Response/ResponseManager.js @@ -8,69 +8,61 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class ResponseManager { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor() + { + this.messages = {}; + }; - /** @namespace jsOMS.Message.Response */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Response'); + /** + * Add response handler. + * + * This allows the response handler to generally handle responses and also handle specific requests if defined. + * + * @param {string} key Response key + * @param {requestCallback} message Callback for message + * @param {string} [request] Request id in order to only handle a specific request + * + * @return {void} + * + * @since 1.0.0 + */ + add(key, message, request) + { + request = typeof request !== 'undefined' ? request : 'any'; + if (typeof this.messages[key] === 'undefined') { + this.messages[key] = []; + } - jsOMS.Message.Response.ResponseManager = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor() - { - this.messages = {}; - }; + this.messages[key][request] = message; + }; - /** - * Add response handler. - * - * This allows the response handler to generally handle responses and also handle specific requests if defined. - * - * @param {string} key Response key - * @param {requestCallback} message Callback for message - * @param {string} [request] Request id in order to only handle a specific request - * - * @return {void} - * - * @since 1.0.0 - */ - add(key, message, request) - { - request = typeof request !== 'undefined' ? request : 'any'; - if (typeof this.messages[key] === 'undefined') { - this.messages[key] = []; - } - - this.messages[key][request] = message; - }; - - /** - * Execute a predefined callback. - * - * Tries to execute a request specific callback or otherwise a general callback if defined. - * - * @param {string} key Response key - * @param {Array|Object} data Date to use in callback - * @param {jsOMS.Message.Request.Request} [request] Request id for request specific execution - * - * @return {void} - * - * @since 1.0.0 - */ - run(key, data, request) - { - if (typeof request !== 'undefined' && typeof this.messages[key] !== 'undefined' && typeof this.messages[key][request] !== 'undefined') { - this.messages[key][request](data); - } else if (typeof this.messages[key] !== 'undefined') { - this.messages[key].any(data); - } else { - jsOMS.Log.Logger.instance.warning('Undefined type: ' + key); - } - }; - } -}(window.jsOMS = window.jsOMS || {})); + /** + * Execute a predefined callback. + * + * Tries to execute a request specific callback or otherwise a general callback if defined. + * + * @param {string} key Response key + * @param {Array|Object} data Date to use in callback + * @param {jsOMS.Message.Request.Request} [request] Request id for request specific execution + * + * @return {void} + * + * @since 1.0.0 + */ + run(key, data, request) + { + if (typeof request !== 'undefined' && typeof this.messages[key] !== 'undefined' && typeof this.messages[key][request] !== 'undefined') { + this.messages[key][request](data); + } else if (typeof this.messages[key] !== 'undefined') { + this.messages[key].any(data); + } else { + jsOMS.Log.Logger.instance.warning('Undefined type: ' + key); + } + }; +}; diff --git a/Message/Response/ResponseType.js b/Message/Response/ResponseType.js index c1eac59..f157f95 100644 --- a/Message/Response/ResponseType.js +++ b/Message/Response/ResponseType.js @@ -6,19 +6,11 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.Message.Response */ - jsOMS.Autoloader.defineNamespace('jsOMS.Message.Response'); - - jsOMS.Message.Response.ResponseType = Object.freeze({ - TEXT: 'text', - JSON: 'json', - DOCUMENT: 'document', - BLOB: 'blob', - ARRAYBUFFER: 'arraybuffer', - DEFAULT: '' - }); -}(window.jsOMS = window.jsOMS || {})); +export const ResponseType = Object.freeze({ + TEXT: 'text', + JSON: 'json', + DOCUMENT: 'document', + BLOB: 'blob', + ARRAYBUFFER: 'arraybuffer', + DEFAULT: '' +}); diff --git a/Model/Action/Dom/Datalist/Append.js b/Model/Action/Dom/Datalist/Append.js index 2611ffc..4a1dcc6 100644 --- a/Model/Action/Dom/Datalist/Append.js +++ b/Model/Action/Dom/Datalist/Append.js @@ -6,7 +6,7 @@ * * @since 1.0.0 */ -const datalistAppend = function (action, callback) +export function datalistAppend (action, callback) { "use strict"; diff --git a/Model/Action/Dom/Datalist/Clear.js b/Model/Action/Dom/Datalist/Clear.js index a440e5d..8f78f0e 100644 --- a/Model/Action/Dom/Datalist/Clear.js +++ b/Model/Action/Dom/Datalist/Clear.js @@ -6,7 +6,7 @@ * * @since 1.0.0 */ -const datalistClear = function (action, callback) +export function datalistClear (action, callback) { "use strict"; diff --git a/Model/Action/Dom/Focus.js b/Model/Action/Dom/Focus.js index 975f288..41a25b6 100644 --- a/Model/Action/Dom/Focus.js +++ b/Model/Action/Dom/Focus.js @@ -1,4 +1,4 @@ -const focusAction = function (action, callback) +export function focusAction (action, callback) { "use strict"; diff --git a/Model/Action/Dom/GetValue.js b/Model/Action/Dom/GetValue.js index e3cef9e..68b4b0f 100644 --- a/Model/Action/Dom/GetValue.js +++ b/Model/Action/Dom/GetValue.js @@ -7,7 +7,7 @@ * * @since 1.0.0 */ -const domGetValue = function (action, callback, id) +export function domGetValue (action, callback, id) { "use strict"; diff --git a/Model/Action/Dom/Hide.js b/Model/Action/Dom/Hide.js index cf26b44..0011ff1 100644 --- a/Model/Action/Dom/Hide.js +++ b/Model/Action/Dom/Hide.js @@ -1,4 +1,4 @@ -const hideAction = function (action, callback) +export function hideAction (action, callback) { "use strict"; diff --git a/Model/Action/Dom/Popup.js b/Model/Action/Dom/Popup.js index cbeb591..0cb0b93 100644 --- a/Model/Action/Dom/Popup.js +++ b/Model/Action/Dom/Popup.js @@ -7,7 +7,7 @@ * * @since 1.0.0 */ -const popupButtonAction = function (action, callback, id) +export function popupButtonAction (action, callback, id) { "use strict"; diff --git a/Model/Action/Dom/Remove.js b/Model/Action/Dom/Remove.js index ecd5cac..b3a4e7c 100644 --- a/Model/Action/Dom/Remove.js +++ b/Model/Action/Dom/Remove.js @@ -7,7 +7,7 @@ * * @since 1.0.0 */ -const removeButtonAction = function (action, callback, id) +export function removeButtonAction (action, callback, id) { "use strict"; diff --git a/Model/Action/Dom/RemoveValue.js b/Model/Action/Dom/RemoveValue.js index 87579f9..5c0998e 100644 --- a/Model/Action/Dom/RemoveValue.js +++ b/Model/Action/Dom/RemoveValue.js @@ -7,7 +7,7 @@ * * @since 1.0.0 */ -const domRemoveValue = function (action, callback, id) +export function domRemoveValue (action, callback, id) { "use strict"; diff --git a/Model/Action/Dom/SetValue.js b/Model/Action/Dom/SetValue.js index 1b190a3..84929ef 100644 --- a/Model/Action/Dom/SetValue.js +++ b/Model/Action/Dom/SetValue.js @@ -7,7 +7,7 @@ * * @since 1.0.0 */ -const domSetValue = function (action, callback, id) +export function domSetValue (action, callback, id) { "use strict"; diff --git a/Model/Action/Dom/Show.js b/Model/Action/Dom/Show.js index 8cec817..d63877e 100644 --- a/Model/Action/Dom/Show.js +++ b/Model/Action/Dom/Show.js @@ -1,4 +1,4 @@ -const showAction = function (action, callback) +export function showAction (action, callback) { "use strict"; diff --git a/Model/Action/Dom/Table/Append.js b/Model/Action/Dom/Table/Append.js index edfbb3c..30653fc 100644 --- a/Model/Action/Dom/Table/Append.js +++ b/Model/Action/Dom/Table/Append.js @@ -6,7 +6,7 @@ * * @since 1.0.0 */ -const tableAppend = function (action, callback) +export function tableAppend (action, callback) { "use strict"; diff --git a/Model/Action/Dom/Table/Clear.js b/Model/Action/Dom/Table/Clear.js index a3d9b65..e4d7a3b 100644 --- a/Model/Action/Dom/Table/Clear.js +++ b/Model/Action/Dom/Table/Clear.js @@ -6,7 +6,7 @@ * * @since 1.0.0 */ -const tableClear = function (action, callback) +export function tableClear (action, callback) { "use strict"; diff --git a/Model/Action/Event/Prevent.js b/Model/Action/Event/Prevent.js index 53ca316..1fd513b 100644 --- a/Model/Action/Event/Prevent.js +++ b/Model/Action/Event/Prevent.js @@ -7,7 +7,7 @@ * * @since 1.0.0 */ -const preventEvent = function (action, callback, id) +export function preventEvent (action, callback, id) { "use strict"; diff --git a/Model/Action/Message/Log.js b/Model/Action/Message/Log.js index 71bec28..808ac64 100644 --- a/Model/Action/Message/Log.js +++ b/Model/Action/Message/Log.js @@ -6,7 +6,7 @@ * * @since 1.0.0 */ -const logAction = function (action, callback) +export function logAction (action, callback) { "use strict"; diff --git a/Model/Action/Message/Request.js b/Model/Action/Message/Request.js index b0a9729..5d5a9f7 100644 --- a/Model/Action/Message/Request.js +++ b/Model/Action/Message/Request.js @@ -6,7 +6,7 @@ * * @since 1.0.0 */ -const requestAction = function (action, callback) +export function requestAction (action, callback) { "use strict"; diff --git a/Model/Action/Utils/DataCollector.js b/Model/Action/Utils/DataCollector.js index 48a80e9..3d44e9d 100644 --- a/Model/Action/Utils/DataCollector.js +++ b/Model/Action/Utils/DataCollector.js @@ -6,7 +6,7 @@ * * @since 1.0.0 */ -const dataCollectionAction = function (action, callback) +export function dataCollectionAction (action, callback) { "use strict"; diff --git a/Model/Action/Utils/Timer.js b/Model/Action/Utils/Timer.js index c847633..22f163d 100644 --- a/Model/Action/Utils/Timer.js +++ b/Model/Action/Utils/Timer.js @@ -7,7 +7,7 @@ * @since 1.0.0 */ const timerActionDelay = {}; -const timerAction = function (action, callback, data) +export function timerAction (action, callback, data) { "use strict"; diff --git a/Model/Action/Validate/Keypress.js b/Model/Action/Validate/Keypress.js index e5088ad..f5fd5b0 100644 --- a/Model/Action/Validate/Keypress.js +++ b/Model/Action/Validate/Keypress.js @@ -6,7 +6,7 @@ * * @since 1.0.0 */ -const validateKeypress = function (action, callback) +export function validateKeypress (action, callback) { "use strict"; diff --git a/Model/Message/DomAction.js b/Model/Message/DomAction.js index 52f68ca..86fe19a 100644 --- a/Model/Message/DomAction.js +++ b/Model/Message/DomAction.js @@ -5,7 +5,7 @@ * * @since 1.0.0 */ -const domAction = function (data) +export function domAction (data) { /** global: jsOMS */ setTimeout(function () diff --git a/Model/Message/DomActionType.js b/Model/Message/DomActionType.js index a006d1e..cbdef2f 100644 --- a/Model/Message/DomActionType.js +++ b/Model/Message/DomActionType.js @@ -1,15 +1,11 @@ -(function (jsOMS) { - "use strict"; - - jsOMS.EnumDomActionType = Object.freeze({ - CREATE_BEFORE: 0, - CREATE_AFTER: 1, - DELETE: 2, - REPLACE: 3, - MODIFY: 4, - SHOW: 5, - HIDE: 6, - ACTIVATE: 7, - DEACTIVATE: 8 - }); -} (window.jsOMS = window.jsOMS || {})); +export const EnumDomActionType = Object.freeze({ + CREATE_BEFORE: 0, + CREATE_AFTER: 1, + DELETE: 2, + REPLACE: 3, + MODIFY: 4, + SHOW: 5, + HIDE: 6, + ACTIVATE: 7, + DEACTIVATE: 8 +}); diff --git a/Model/Message/FormValidation.js b/Model/Message/FormValidation.js index e6d7b46..ad39c08 100644 --- a/Model/Message/FormValidation.js +++ b/Model/Message/FormValidation.js @@ -5,7 +5,7 @@ * * @since 1.0.0 */ -const formValidationMessage = function (data) { +export function formValidationMessage (data) { const form = document.getElementById(data.form); if(!form) { diff --git a/Model/Message/Notify.js b/Model/Message/Notify.js index efdc8b1..2b25145 100644 --- a/Model/Message/Notify.js +++ b/Model/Message/Notify.js @@ -5,7 +5,7 @@ * * @since 1.0.0 */ -const notifyMessage = function (data) +export function notifyMessage (data) { setTimeout(function () { diff --git a/Model/Message/NotifyType.js b/Model/Message/NotifyType.js index 67d8b1b..45444b3 100644 --- a/Model/Message/NotifyType.js +++ b/Model/Message/NotifyType.js @@ -1,11 +1,8 @@ -(function (jsOMS) { - "use strict"; +export const EnumNotifyType = Object.freeze({ + BINARY: 0, + INFO: 1, + WARNING: 2, + ERROR: 3, + FATAL: 4 +}); - jsOMS.EnumNotifyType = Object.freeze({ - BINARY: 0, - INFO: 1, - WARNING: 2, - ERROR: 3, - FATAL: 4 - }); -}(window.jsOMS = window.jsOMS || {})); diff --git a/Model/Message/Redirect.js b/Model/Message/Redirect.js index 471c4ef..1595926 100644 --- a/Model/Message/Redirect.js +++ b/Model/Message/Redirect.js @@ -1,3 +1,5 @@ +import { UriFactory } from '../../Uri/UriFactory.js'; + /** * Set message. * @@ -5,11 +7,11 @@ * * @since 1.0.0 */ -const redirectMessage = function (data) +export function redirectMessage (data) { setTimeout(function () { /** global: jsOMS */ - window.location = jsOMS.Uri.UriFactory.build(data.uri); + window.location = UriFactory.build(data.uri); }, parseInt(data.delay)); }; diff --git a/Model/Message/Reload.js b/Model/Message/Reload.js index f80e400..820a2b9 100644 --- a/Model/Message/Reload.js +++ b/Model/Message/Reload.js @@ -5,7 +5,7 @@ * * @since 1.0.0 */ -const reloadMessage = function (data) { +export function reloadMessage (data) { setTimeout(function () { document.location.reload(true); }, parseInt(data.delay)); diff --git a/Module/ModuleFactory.js b/Module/ModuleFactory.js index 9c39c11..63f2848 100644 --- a/Module/ModuleFactory.js +++ b/Module/ModuleFactory.js @@ -6,35 +6,28 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class ModuleFactory { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + }; - jsOMS.Autoloader.defineNamespace('jsOMS.Module'); - - jsOMS.Module.ModuleFactory = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () - { - }; - - /** - * Get module instance. - * - * @param {string} module Module name - * @param {Object} app Application reference - * - * @return {Object} - * - * @since 1.0.0 - */ - static getInstance (module, app) - { - return new jsOMS.Modules[module](app); - }; - } -}(window.jsOMS = window.jsOMS || {})); + /** + * Get module instance. + * + * @param {string} module Module name + * @param {Object} app Application reference + * + * @return {Object} + * + * @since 1.0.0 + */ + static getInstance (module, app) + { + return new jsOMS.Modules[module](app); + }; +}; diff --git a/Module/ModuleManager.js b/Module/ModuleManager.js index 8ee2348..939dd79 100644 --- a/Module/ModuleManager.js +++ b/Module/ModuleManager.js @@ -1,3 +1,4 @@ +import { ModuleFactory } from './ModuleFactory.js'; /** * Module manager. * @@ -6,43 +7,35 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class ModuleManager { + /** + * @constructor + * + * @param {Object} app Application + * + * @since 1.0.0 + */ + constructor(app) + { + this.modules = {}; + this.app = app; + }; - /** @namespace jsOMS.Module */ - jsOMS.Autoloader.defineNamespace('jsOMS.Module'); + /** + * Get module. + * + * @param {string} module Module name + * + * @return {Object} + * + * @since 1.0.0 + */ + get (module) + { + if (typeof this.modules[module] === 'undefined') { + this.modules[module] = ModuleFactory.getInstance(module, this.app); + } - jsOMS.Module.ModuleManager = class { - /** - * @constructor - * - * @param {Object} app Application - * - * @since 1.0.0 - */ - constructor(app) - { - this.modules = {}; - this.app = app; - }; - - /** - * Get module. - * - * @param {string} module Module name - * - * @return {Object} - * - * @since 1.0.0 - */ - get (module) - { - if (typeof this.modules[module] === 'undefined') { - this.modules[module] = jsOMS.Module.ModuleFactory.getInstance(module, this.app); - } - - return this.modules[module]; - }; - } -}(window.jsOMS = window.jsOMS || {})); + return this.modules[module]; + }; +}; \ No newline at end of file diff --git a/UI/ActionManager.js b/UI/ActionManager.js index 90b8841..dd72b52 100644 --- a/UI/ActionManager.js +++ b/UI/ActionManager.js @@ -6,192 +6,184 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class ActionManager { + /** + * @constructor + * + * @param {Object} app Application + * + * @since 1.0.0 + */ + constructor(app) + { + this.app = app; + this.actions = {}; + }; - /** @namespace jsOMS.UI */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.ActionManager'); + /** + * Bind element. + * + * @param {string} [id] Element id (optional) + * + * @return {void} + * + * @since 1.0.0 + */ + bind(id) + { + const uiElements = typeof id === 'undefined' ? document.querySelectorAll('[data-action]') : (typeof id.length !== 'undefined' ? id : [id]), + length = uiElements.length; - jsOMS.UI.ActionManager = class { - /** - * @constructor - * - * @param {Object} app Application - * - * @since 1.0.0 - */ - constructor(app) - { - this.app = app; - this.actions = {}; - }; - - /** - * Bind element. - * - * @param {string} [id] Element id (optional) - * - * @return {void} - * - * @since 1.0.0 - */ - bind(id) - { - const uiElements = typeof id === 'undefined' ? document.querySelectorAll('[data-action]') : (typeof id.length !== 'undefined' ? id : [id]), - length = uiElements.length; - - for (let i = 0; i < length; ++i) { - if (uiElements[i] !== null && uiElements[i].hasAttribute('data-action')) { - this.bindElement(uiElements[i]); - } + for (let i = 0; i < length; ++i) { + if (uiElements[i] !== null && uiElements[i].hasAttribute('data-action')) { + this.bindElement(uiElements[i]); } - }; + } + }; - /** - * Bind element. - * - * @param {Element} e Element to bind - * - * @return {void} - * - * @since 1.0.0 - */ - bindElement (e) - { - if (!jsOMS.isValidJson(e.getAttribute('data-action'))) { - jsOMS.Log.Logger.instance.error('Invalid json string: \'' + e.getAttribute('data-action') + '\''); + /** + * Bind element. + * + * @param {Element} e Element to bind + * + * @return {void} + * + * @since 1.0.0 + */ + bindElement (e) + { + if (!jsOMS.isValidJson(e.getAttribute('data-action'))) { + jsOMS.Log.Logger.instance.error('Invalid json string: \'' + e.getAttribute('data-action') + '\''); + return; + } + + // todo: validate json, if invalid log error + const listeners = JSON.parse(e.getAttribute('data-action')), + listenerLength = listeners.length, + self = this; + + // For everey action an event is registered + for (let i = 0; i < listenerLength; ++i) { + let c = [e], hasSelector = false; + + if (listeners[i].hasOwnProperty('selector')) { + c = document.querySelectorAll(listeners[i].selector); + hasSelector = true; + } + + let childLength = c.length; + for (let j = 0; j < childLength; ++j) { + this.bindListener(c[j].id, listeners[i]); + } + + // if it has selector then a listener for child events must be implemented since these can potentially changed without any knowledge + // todo: what if the selector parent is different from "e"? then this doesn't make sense! Maybe this isn't allowed to happen! + // todo: careful this could cause bugs if there is another component relying on a listener for this dom element. Maybe create actionManager domlistener? + // Maybe just use this listener for ALL action listeners and check if delete, then remove otherwise do current stuff. + // Problem is, the listener doesn't work for the node itself only for children and listening to ALL document nodes might be a bad idea?!?!?! + const observeConfig = { childList: false, attributes: true, subtree: false }; + + if (hasSelector) { + this.app.eventManager.attach(e.id + '-childList', function(data) { + const length = data.addedNodes.length; + + for (let j = 0; j < length; ++j) { + self.bindListener(data.addedNodes[j].id, listeners[i], true); + // todo only make removable if action itself is defined as auto removable + } + }); + + observeConfig.childList = true; + observeConfig.subtree = true; + } + + this.app.eventManager.attach(e.id + '-attributes', function(data) {}); + this.app.uiManager.getDOMObserver().observe(e, observeConfig); + } + }; + + /** + * Bind listener for object + * + * @param {string} id Element to bind + * @param {object} listener Listener object + * + * @return {void} + * + * @since 1.0.0 + */ + bindListener (id, listener, removable = false) + { + const self = this, + actionLength = listener.action.length; + + for (let j = 1; j < actionLength; ++j) { + if (typeof id === 'undefined' || typeof listener.key === 'undefined') { + jsOMS.Log.Logger.instance.error('Invalid element id/key: ' + id + '/' + listener.key); return; } - // todo: validate json, if invalid log error - const listeners = JSON.parse(e.getAttribute('data-action')), - listenerLength = listeners.length, - self = this; - - // For everey action an event is registered - for (let i = 0; i < listenerLength; ++i) { - let c = [e], hasSelector = false; - - if (listeners[i].hasOwnProperty('selector')) { - c = document.querySelectorAll(listeners[i].selector); - hasSelector = true; - } - - let childLength = c.length; - for (let j = 0; j < childLength; ++j) { - this.bindListener(c[j].id, listeners[i]); - } - - // if it has selector then a listener for child events must be implemented since these can potentially changed without any knowledge - // todo: what if the selector parent is different from "e"? then this doesn't make sense! Maybe this isn't allowed to happen! - // todo: careful this could cause bugs if there is another component relying on a listener for this dom element. Maybe create actionManager domlistener? - // Maybe just use this listener for ALL action listeners and check if delete, then remove otherwise do current stuff. - // Problem is, the listener doesn't work for the node itself only for children and listening to ALL document nodes might be a bad idea?!?!?! - const observeConfig = { childList: false, attributes: true, subtree: false }; - - if (hasSelector) { - this.app.eventManager.attach(e.id + '-childList', function(data) { - const length = data.addedNodes.length; - - for (let j = 0; j < length; ++j) { - self.bindListener(data.addedNodes[j].id, listeners[i], true); - // todo only make removable if action itself is defined as auto removable - } - }); - - observeConfig.childList = true; - observeConfig.subtree = true; - } - - this.app.eventManager.attach(e.id + '-attributes', function(data) {}); - this.app.uiManager.getDOMObserver().observe(e, observeConfig); - } - }; - - /** - * Bind listener for object - * - * @param {string} id Element to bind - * @param {object} listener Listener object - * - * @return {void} - * - * @since 1.0.0 - */ - bindListener (id, listener, removable = false) - { - const self = this, - actionLength = listener.action.length; - - for (let j = 1; j < actionLength; ++j) { - if (typeof id === 'undefined' || typeof listener.key === 'undefined') { - jsOMS.Log.Logger.instance.error('Invalid element id/key: ' + id + '/' + listener.key); - return; - } - - this.app.eventManager.attach(id + '-' + listener.key + '-' + listener.action[j - 1].key, function (data) - { - self.runAction(id, listener, listener.action[j], data); - }, removable, true); - } - // todo: the true here is a memory leak since it should be removed at some point?! - // todo: handle onload action right after registering everything. this will be used for onload api calls in order to get content such as lists or models. Maybe in the main application after registering a invoke('onload') should be called if the application wants to execute the onload elements - - // Register event for first action - document.getElementById(id).addEventListener(listener.listener, function (event) + this.app.eventManager.attach(id + '-' + listener.key + '-' + listener.action[j - 1].key, function (data) { - if (listener.preventDefault) { - jsOMS.preventAll(event); - } + self.runAction(id, listener, listener.action[j], data); + }, removable, true); + } + // todo: the true here is a memory leak since it should be removed at some point?! + // todo: handle onload action right after registering everything. this will be used for onload api calls in order to get content such as lists or models. Maybe in the main application after registering a invoke('onload') should be called if the application wants to execute the onload elements - self.runAction(this.id, listener, listener.action[0], event); - }); - }; - - /** - * Run event action. - * - * @param {string} id Element - * @param {Object} listener Listener - * @param {Object} action Action - * @param {Object} data Data for the next action - * - * @return {void} - * - * @since 1.0.0 - */ - runAction (id, listener, action, data) + // Register event for first action + document.getElementById(id).addEventListener(listener.listener, function (event) { - const self = this; - - if (!this.actions.hasOwnProperty(action.type)) { - jsOMS.Log.Logger.instance.warning('Undefined action ' + action.type); - return; + if (listener.preventDefault) { + jsOMS.preventAll(event); } - action.data = data; + self.runAction(this.id, listener, listener.action[0], event); + }); + }; - this.actions[action.type](action, function (data) - { - self.app.eventManager.trigger(id + '-' + listener.key + '-' + action.key, id, data); - }, id); - }; + /** + * Run event action. + * + * @param {string} id Element + * @param {Object} listener Listener + * @param {Object} action Action + * @param {Object} data Data for the next action + * + * @return {void} + * + * @since 1.0.0 + */ + runAction (id, listener, action, data) + { + const self = this; - /** - * Add action callback. - * - * @param {string} name Action identifier - * @param {function} callback Action callback - * - * @return {void} - * - * @since 1.0.0 - */ - add (name, callback) + if (!this.actions.hasOwnProperty(action.type)) { + jsOMS.Log.Logger.instance.warning('Undefined action ' + action.type); + return; + } + + action.data = data; + + this.actions[action.type](action, function (data) { - this.actions[name] = callback; - }; - } -}(window.jsOMS = window.jsOMS || {})); + self.app.eventManager.trigger(id + '-' + listener.key + '-' + action.key, id, data); + }, id); + }; + + /** + * Add action callback. + * + * @param {string} name Action identifier + * @param {function} callback Action callback + * + * @return {void} + * + * @since 1.0.0 + */ + add (name, callback) + { + this.actions[name] = callback; + }; +}; \ No newline at end of file diff --git a/UI/Component/AdvancedInput.js b/UI/Component/AdvancedInput.js index a2721f4..731334d 100644 --- a/UI/Component/AdvancedInput.js +++ b/UI/Component/AdvancedInput.js @@ -1,3 +1,4 @@ +import { Request } from '../../Message/Request/Request.js'; /** * Advanced input class. * @@ -9,321 +10,313 @@ * @todo: this class is probably the most stupid thing I've done in a long time. Seriously fix this! * @todo: Passing self to every MEMBER function is just dumb. */ -(function (jsOMS) -{ - "use strict"; +export class AdvancedInput { + /** + * @constructor + * + * @param {object} e Element to bind + * + * @since 1.0.0 + */ + constructor (e) + { + this.id = e.id; + this.inputComponent = e; + this.inputField = this.inputComponent.getElementsByClassName('input')[0]; + this.dropdownElement = document.getElementById(this.id + '-dropdown'); + this.tagElement = document.getElementById(this.id + '-tags'); + this.dataList = this.dropdownElement.getElementsByTagName('table')[0]; + this.dataListBody = this.dataList.getElementsByTagName('tbody')[0]; + this.dataTpl = document.getElementById(this.id + '-rowElement'); + this.tagTpl = this.tagElement.getElementsByTagName('template')[0]; + this.src = this.inputField.getAttribute('data-src'); - /** @namespace jsOMS.UI */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Component'); - - jsOMS.UI.Component.AdvancedInput = class { - /** - * @constructor - * - * @param {object} e Element to bind - * - * @since 1.0.0 - */ - constructor (e) - { - this.id = e.id; - this.inputComponent = e; - this.inputField = this.inputComponent.getElementsByClassName('input')[0]; - this.dropdownElement = document.getElementById(this.id + '-dropdown'); - this.tagElement = document.getElementById(this.id + '-tags'); - this.dataList = this.dropdownElement.getElementsByTagName('table')[0]; - this.dataListBody = this.dataList.getElementsByTagName('tbody')[0]; - this.dataTpl = document.getElementById(this.id + '-rowElement'); - this.tagTpl = this.tagElement.getElementsByTagName('template')[0]; - this.src = this.inputField.getAttribute('data-src'); - - const self = this; - this.inputField.addEventListener('focusout', function(e) { - // todo: this also means that clicking on any other part of the result list that it disappears befor - // the click is registered in the result list since focusout has highest priority (e.g. sort button in table). - // so far i don't know a way to check if *any* element in the result div is clicked, if I could check this - // first then I could simply say, don't make the result div inactive! - if (e.relatedTarget === null || - e.relatedTarget.parentElement === null || - e.relatedTarget.parentElement.parentElement === null || - !jsOMS.hasClass(e.relatedTarget.parentElement.parentElement.parentElement, 'dropdown') - ) { - jsOMS.removeClass(self.dropdownElement, 'active'); - } - }); - - this.inputField.addEventListener('keydown', function(e) { - if (e.keyCode === 13 || e.keyCode === 40) { - jsOMS.preventAll(e); - } - - if (e.keyCode === 40) { - // down-key - self.selectOption(self.dataListBody.firstElementChild); - jsOMS.preventAll(e); - } else { - // handle change delay - self.inputTimeDelay({id: self.id, delay: 300}, self.changeCallback, self, e); - } - }); - - this.inputField.addEventListener('focusin', function(e) { - jsOMS.addClass(self.dropdownElement, 'active'); - }); - - this.dropdownElement.addEventListener('keydown', function(e) { - jsOMS.preventAll(e); - - // todo: consider if it makes sense to have a none element always for phone users only to jump out? - // todo: if not remote then the suggestion dropdown should filter itself based on best match - - if (e.keyCode === 27 || e.keyCode === 46 || e.keyCode === 8) { - // handle esc, del to go back to input field - self.inputField.focus(); - self.clearDataListSelection(self); - } else if (e.keyCode === 38) { - // handle up-click - if (document.activeElement.previousElementSibling !== null) { - self.clearDataListSelection(self); - self.selectOption(document.activeElement.previousElementSibling); - } - } else if (e.keyCode === 40) { - // handle down-click - if (document.activeElement.nextElementSibling !== null) { - self.clearDataListSelection(self); - self.selectOption(document.activeElement.nextElementSibling); - } - } else if (e.keyCode === 13 || e.keyCode === 9) { - self.clearDataListSelection(self); - self.addToResultList(self); - } - }); - - this.dropdownElement.addEventListener('focusout', function(e) { - self.clearDataListSelection(self); + const self = this; + this.inputField.addEventListener('focusout', function(e) { + // todo: this also means that clicking on any other part of the result list that it disappears befor + // the click is registered in the result list since focusout has highest priority (e.g. sort button in table). + // so far i don't know a way to check if *any* element in the result div is clicked, if I could check this + // first then I could simply say, don't make the result div inactive! + if (e.relatedTarget === null || + e.relatedTarget.parentElement === null || + e.relatedTarget.parentElement.parentElement === null || + !jsOMS.hasClass(e.relatedTarget.parentElement.parentElement.parentElement, 'dropdown') + ) { jsOMS.removeClass(self.dropdownElement, 'active'); - }); + } + }); - this.dropdownElement.addEventListener('click', function(e) { - if (document.activeElement.tagName.toLowerCase() !== 'tr') { - return; + this.inputField.addEventListener('keydown', function(e) { + if (e.keyCode === 13 || e.keyCode === 40) { + jsOMS.preventAll(e); + } + + if (e.keyCode === 40) { + // down-key + self.selectOption(self.dataListBody.firstElementChild); + jsOMS.preventAll(e); + } else { + // handle change delay + self.inputTimeDelay({id: self.id, delay: 300}, self.changeCallback, self, e); + } + }); + + this.inputField.addEventListener('focusin', function(e) { + jsOMS.addClass(self.dropdownElement, 'active'); + }); + + this.dropdownElement.addEventListener('keydown', function(e) { + jsOMS.preventAll(e); + + // todo: consider if it makes sense to have a none element always for phone users only to jump out? + // todo: if not remote then the suggestion dropdown should filter itself based on best match + + if (e.keyCode === 27 || e.keyCode === 46 || e.keyCode === 8) { + // handle esc, del to go back to input field + self.inputField.focus(); + self.clearDataListSelection(self); + } else if (e.keyCode === 38) { + // handle up-click + if (document.activeElement.previousElementSibling !== null) { + self.clearDataListSelection(self); + self.selectOption(document.activeElement.previousElementSibling); } - + } else if (e.keyCode === 40) { + // handle down-click + if (document.activeElement.nextElementSibling !== null) { + self.clearDataListSelection(self); + self.selectOption(document.activeElement.nextElementSibling); + } + } else if (e.keyCode === 13 || e.keyCode === 9) { self.clearDataListSelection(self); self.addToResultList(self); - jsOMS.removeClass(self.dropdownElement, 'active'); - }); - }; - - /** - * Handle remote data response result - * - * This method adds remote results to the dropdown list for selecting - * - * @param {object} self This reference - * @param {object} data Response data - * - * @since 1.0.0 - */ - remoteCallback(self, data) - { - data = JSON.parse(data.response); - const dataLength = data.length; - - console.table(data); - - // if dropdown == true - if (self.dropdownElement.getAttribute('data-active') === 'true') { - while (self.dataListBody.firstChild) { - self.dataListBody.removeChild(self.dataListBody.firstChild); - } - - 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]) - ); - } - - self.dataListBody.appendChild(newRow); - self.dataListBody.lastElementChild.addEventListener('focusout', function(e) { - if (e.relatedTarget === null) { - return; - } - - let sibling = e.relatedTarget.parentNode.firstElementChild; - do { - if (sibling === e.relatedTarget) { - jsOMS.preventAll(e); - return; - } - } while ((sibling = sibling.nextElementSibling) !== null); - }); - } } - }; + }); - /** - * Callback for input field content change - * - * @param {object} self This reference - * - * @since 1.0.0 - */ - changeCallback(self) - { - // if remote data - if (typeof self.src !== 'undefined' && self.src !== '') { - const request = new jsOMS.Message.Request.Request(self.src); - request.setSuccess(function (data) { self.remoteCallback(self, data); }); - request.send(); - } - }; + this.dropdownElement.addEventListener('focusout', function(e) { + self.clearDataListSelection(self); + jsOMS.removeClass(self.dropdownElement, 'active'); + }); - /** - * Select element in dropdown (only mark it as selected) - * - * @param {object} e Element to select in dropdown - * - * @since 1.0.0 - */ - selectOption(e) - { - e.focus(); - // todo: change to set style .active - e.setAttribute('style', 'background: #f00'); - jsOMS.addClass(e, 'active'); - }; - - /** - * Clear all selected/marked options in dropdown - * - * @param {object} self This reference - * - * @since 1.0.0 - */ - clearDataListSelection(self) - { - const list = self.dataListBody.getElementsByTagName('tr'), - length = list.length; - - for (let i = 0; i < length; ++i) { - // todo: remove the active class - list[i].setAttribute('style', ''); - 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 {object} self This reference - * - * @since 1.0.0 - */ - addToResultList(self) { - if (self.inputField.getAttribute('data-autocomplete') === 'true') { - self.inputField.value = document.activeElement.querySelectorAll('[data-tpl-value="' + self.inputField.getAttribute('data-value') + '"]')[0].getAttribute('data-value'); + this.dropdownElement.addEventListener('click', function(e) { + if (document.activeElement.tagName.toLowerCase() !== 'tr') { + return; } - if (self.tagElement.getAttribute('data-active') === 'true') { - // todo: make badges removable - const newTag = self.tagTpl.content.cloneNode(true); + self.clearDataListSelection(self); + self.addToResultList(self); + jsOMS.removeClass(self.dropdownElement, 'active'); + }); + }; - // set internal value - let fields = newTag.querySelectorAll('[data-tpl-value]'); + /** + * Handle remote data response result + * + * This method adds remote results to the dropdown list for selecting + * + * @param {object} self This reference + * @param {object} data Response data + * + * @since 1.0.0 + */ + remoteCallback(self, data) + { + data = JSON.parse(data.response); + const dataLength = data.length; + + console.table(data); + + // if dropdown == true + if (self.dropdownElement.getAttribute('data-active') === 'true') { + while (self.dataListBody.firstChild) { + self.dataListBody.removeChild(self.dataListBody.firstChild); + } + + 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; - let uuid = ''; - let value = ''; - - for (let j = 0; j < fieldLength; ++j) { - value = document.activeElement.querySelectorAll('[data-tpl-value="' + newTag.firstElementChild.getAttribute('data-tpl-value') + '"]')[0].getAttribute('data-value'); - fields[j].setAttribute('data-value', value); - - uuid += value; - } - - // don't allow duplicate - if (self.tagElement.querySelectorAll('[data-tpl-uuid="' + uuid + '"').length !== 0) { - return; - } - - newTag.firstElementChild.setAttribute('data-tpl-uuid', uuid); - - // set readable text - fields = newTag.querySelectorAll('[data-tpl-text]'); - fieldLength = fields.length; for (let j = 0; j < fieldLength; ++j) { fields[j].appendChild( document.createTextNode( - document.activeElement.querySelectorAll('[data-tpl-text="' + fields[j].getAttribute('data-tpl-text') + '"]')[0].innerText + jsOMS.getArray(fields[j].getAttribute('data-tpl-text'), data[i]) ) ); } - // allow limit - if (self.tagElement.childElementCount >= self.tagElement.getAttribute('data-limit') - && self.tagElement.getAttribute('data-limit') != 0 - ) { - self.tagElement.removeChild(self.tagElement.firstElementChild); + // 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]) + ); } - self.tagElement.appendChild(newTag); + self.dataListBody.appendChild(newRow); + self.dataListBody.lastElementChild.addEventListener('focusout', function(e) { + if (e.relatedTarget === null) { + return; + } + + let sibling = e.relatedTarget.parentNode.firstElementChild; + do { + if (sibling === e.relatedTarget) { + jsOMS.preventAll(e); + return; + } + } while ((sibling = sibling.nextElementSibling) !== null); + }); + } + } + }; + + /** + * Callback for input field content change + * + * @param {object} self This reference + * + * @since 1.0.0 + */ + changeCallback(self) + { + // if remote data + if (typeof self.src !== 'undefined' && self.src !== '') { + const request = new Request(self.src); + request.setSuccess(function (data) { self.remoteCallback(self, data); }); + request.send(); + } + }; + + /** + * Select element in dropdown (only mark it as selected) + * + * @param {object} e Element to select in dropdown + * + * @since 1.0.0 + */ + selectOption(e) + { + e.focus(); + // todo: change to set style .active + e.setAttribute('style', 'background: #f00'); + jsOMS.addClass(e, 'active'); + }; + + /** + * Clear all selected/marked options in dropdown + * + * @param {object} self This reference + * + * @since 1.0.0 + */ + clearDataListSelection(self) + { + const list = self.dataListBody.getElementsByTagName('tr'), + length = list.length; + + for (let i = 0; i < length; ++i) { + // todo: remove the active class + list[i].setAttribute('style', ''); + 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 {object} self This reference + * + * @since 1.0.0 + */ + addToResultList(self) { + if (self.inputField.getAttribute('data-autocomplete') === 'true') { + self.inputField.value = document.activeElement.querySelectorAll('[data-tpl-value="' + self.inputField.getAttribute('data-value') + '"]')[0].getAttribute('data-value'); + } + + if (self.tagElement.getAttribute('data-active') === 'true') { + // todo: make badges removable + const newTag = self.tagTpl.content.cloneNode(true); + + // set internal value + let fields = newTag.querySelectorAll('[data-tpl-value]'); + let fieldLength = fields.length; + let uuid = ''; + let value = ''; + + for (let j = 0; j < fieldLength; ++j) { + value = document.activeElement.querySelectorAll('[data-tpl-value="' + newTag.firstElementChild.getAttribute('data-tpl-value') + '"]')[0].getAttribute('data-value'); + fields[j].setAttribute('data-value', value); + + uuid += value; } - if (self.inputField.getAttribute('data-emptyAfter') === 'true') { - self.inputField.value = ''; + // don't allow duplicate + if (self.tagElement.querySelectorAll('[data-tpl-uuid="' + uuid + '"').length !== 0) { + return; } - self.inputField.focus(); - }; + newTag.firstElementChild.setAttribute('data-tpl-uuid', uuid); - /** - * Delay handler (e.g. delay after finishing typing) - * - * After waiting for a delay a callback can be triggered. - * - * @param {object} action Action type - * @param {function} callback Callback to be triggered - * @param {object} self This reference (passed to callback) - * @param {object} data Data (passed to callback) - * - * @since 1.0.0 - */ - inputTimeDelay(action, callback, self, data) - { - if (jsOMS.UI.Component.AdvancedInput.timerDelay[action.id]) { - clearTimeout(jsOMS.UI.Component.AdvancedInput.timerDelay[action.id]); - delete jsOMS.UI.Component.AdvancedInput.timerDelay[action.id] + // set readable text + fields = newTag.querySelectorAll('[data-tpl-text]'); + fieldLength = fields.length; + + for (let j = 0; j < fieldLength; ++j) { + fields[j].appendChild( + document.createTextNode( + document.activeElement.querySelectorAll('[data-tpl-text="' + fields[j].getAttribute('data-tpl-text') + '"]')[0].innerText + ) + ); } - jsOMS.UI.Component.AdvancedInput.timerDelay[action.id] = setTimeout(function() { - delete jsOMS.UI.Component.AdvancedInput.timerDelay[action.id]; - callback(self, data); - }, action.delay); - }; - } + // allow limit + if (self.tagElement.childElementCount >= self.tagElement.getAttribute('data-limit') + && self.tagElement.getAttribute('data-limit') != 0 + ) { + self.tagElement.removeChild(self.tagElement.firstElementChild); + } - jsOMS.UI.Component.AdvancedInput.timerDelay = {}; -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file + self.tagElement.appendChild(newTag); + } + + if (self.inputField.getAttribute('data-emptyAfter') === 'true') { + self.inputField.value = ''; + } + + self.inputField.focus(); + }; + + /** + * Delay handler (e.g. delay after finishing typing) + * + * After waiting for a delay a callback can be triggered. + * + * @param {object} action Action type + * @param {function} callback Callback to be triggered + * @param {object} self This reference (passed to callback) + * @param {object} data Data (passed to callback) + * + * @since 1.0.0 + */ + inputTimeDelay(action, callback, self, data) + { + if (AdvancedInput.timerDelay[action.id]) { + clearTimeout(AdvancedInput.timerDelay[action.id]); + delete AdvancedInput.timerDelay[action.id] + } + + AdvancedInput.timerDelay[action.id] = setTimeout(function() { + delete AdvancedInput.timerDelay[action.id]; + callback(self, data); + }, action.delay); + }; +}; + +AdvancedInput.timerDelay = {}; \ No newline at end of file diff --git a/UI/Component/Form.js b/UI/Component/Form.js index 2785a3c..2b80264 100644 --- a/UI/Component/Form.js +++ b/UI/Component/Form.js @@ -1,3 +1,10 @@ +import { Logger } from '../../Log/Logger.js'; +import { FormView } from '../../Views/FormView.js'; +import { Request } from '../../Message/Request/Request.js'; +import { RequestMethod } from '../../Message/Request/RequestMethod.js'; +import { Response } from '../../Message/Response/Response.js'; +import { ResponseType } from '../../Message/Response/ResponseType.js'; + /** * Form manager class. * @@ -6,301 +13,293 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class Form { + /** + * @constructor + * + * @param {Object} app Application + * + * @since 1.0.0 + */ + constructor (app) + { + this.app = app; + this.forms = {}; + this.ignore = {}; + }; - /** @namespace jsOMS.UI */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Component'); + /** + * Get form + * + * @param {string} id Form Id + * + * @return {void} + * + * @since 1.0.0 + */ + get (id) + { + if (!this.forms.hasOwnProperty(id)) { + this.bind(id); + } - jsOMS.UI.Component.Form = class { - /** - * @constructor - * - * @param {Object} app Application - * - * @since 1.0.0 - */ - constructor (app) - { - this.app = app; - this.forms = {}; - this.ignore = {}; - }; + return this.forms[id]; + }; - /** - * Get form - * - * @param {string} id Form Id - * - * @return {void} - * - * @since 1.0.0 - */ - get (id) - { - if (!this.forms.hasOwnProperty(id)) { - this.bind(id); - } + /** + * Is form ignored? + * + * @param {string} id Form Id + * + * @return {boolean} + * + * @since 1.0.0 + */ + isIgnored (id) + { + return this.ignore.indexOf(id) !== -1; + }; - return this.forms[id]; - }; + /** + * Unbind form + * + * @param {string} id Form Id + * + * @return {void} + * + * @since 1.0.0 + */ + unbind (id) + { - /** - * Is form ignored? - * - * @param {string} id Form Id - * - * @return {boolean} - * - * @since 1.0.0 - */ - isIgnored (id) - { - return this.ignore.indexOf(id) !== -1; - }; + }; - /** - * Unbind form - * - * @param {string} id Form Id - * - * @return {void} - * - * @since 1.0.0 - */ - unbind (id) - { - - }; - - /** - * Bind form - * - * @param {string} id Form Id (optional) - * - * @return {void} - * - * @since 1.0.0 - */ - bind (id) - { - if (typeof id !== 'undefined' && typeof this.ignore[id] === 'undefined') { - this.bindForm(id); - } else { - const forms = document.getElementsByTagName('form'), - length = !forms ? 0 : forms.length; - - for (let i = 0; i < length; ++i) { - let formId = forms[i].getAttribute('id'); - if (typeof formId !== 'undefined' && formId !== null && typeof this.ignore[formId] === 'undefined') { - this.bindForm(formId); - } - } - } - }; - - /** - * Bind form - * - * @param {string} id Form Id - * - * @return {void} - * - * @since 1.0.0 - */ - bindForm (id) - { - if (typeof id === 'undefined' || !id) { - jsOMS.Log.Logger.instance.info('A form doesn\'t have an ID.'); - return; - } - - const self = this; - this.forms[id] = new jsOMS.Views.FormView(id); - - this.unbind(id); - - const submits = this.forms[id].getSubmit(), - length = submits.length; + /** + * Bind form + * + * @param {string} id Form Id (optional) + * + * @return {void} + * + * @since 1.0.0 + */ + bind (id) + { + if (typeof id !== 'undefined' && typeof this.ignore[id] === 'undefined') { + this.bindForm(id); + } else { + const forms = document.getElementsByTagName('form'), + length = !forms ? 0 : forms.length; for (let i = 0; i < length; ++i) { - submits[i].addEventListener('click', function (event) - { - jsOMS.preventAll(event); - self.submit(self.forms[id]); - }); - } - }; - - /** - * Unbind form - * - * @param {string} id Form Id - * - * @return {boolean} - * - * @since 1.0.0 - */ - unbindForm (id) - { - // todo: do i need the findex? can't i just use id? - let findex = 0; - - if ((findex = this.forms[id]) !== 'undefined') { - this.forms[id].unbind(); - this.forms.splice(findex, 1); - - return true; - } - - return false; - }; - - /** - * Submit form - * - * Calls injections first befor executing the actual form submit - * - * @param {Object} form Form object - * - * @return {void} - * - * @since 1.0.0 - */ - submit (form) - { - /* Handle injects */ - const self = this, - injects = form.getSubmitInjects(); - let counter = 0; - - // todo: test if attach necessary (maybe already attached in event manager) - // Register normal form behavior - this.app.eventManager.attach(form.getId(), function () - { - self.submitForm(form); - }, true); - - // Run all injects first - for (let property in injects) { - if (injects.hasOwnProperty(property)) { - ++counter; - //this.app.eventManager.addGroup(form.getId(), counter); - const result = injects[property](form, form.getId()); - - if (result === false) { - return; - } - } else { - jsOMS.Log.Logger.instance.warning('Invalid property.'); + let formId = forms[i].getAttribute('id'); + if (typeof formId !== 'undefined' && formId !== null && typeof this.ignore[formId] === 'undefined') { + this.bindForm(formId); } } + } + }; - if (counter < 1) { - this.app.eventManager.trigger(form.getId()); - } - }; + /** + * Bind form + * + * @param {string} id Form Id + * + * @return {void} + * + * @since 1.0.0 + */ + bindForm (id) + { + if (typeof id === 'undefined' || !id) { + Logger.instance.info('A form doesn\'t have an ID.'); + return; + } - /** - * Submit form data - * - * Submits the main form data - * - * @param {Object} form Form object - * - * @return {void} - * - * @since 1.0.0 - */ - submitForm (form) - { - if (!form.isValid()) { - this.app.notifyManager.send( - new jsOMS.Message.Notification.NotificationMessage(jsOMS.Message.Notification.NotificationLevel.INFO, jsOMS.lang.Info, jsOMS.lang.invalid_form), jsOMS.Message.Notification.NotificationType.APP_NOTIFICATION - ); + const self = this; + this.forms[id] = new FormView(id); - jsOMS.Log.Logger.instance.debug('Form "' + form.getId() + '" has invalid values.'); - return; - } + this.unbind(id); - if (form.getMethod() !== jsOMS.Message.Request.RequestMethod.GET - && Math.abs(Date.now() - form.getLastSubmit()) < 500 - ) { - return; - } + const submits = this.forms[id].getSubmit(), + length = submits.length; - form.updateLastSubmit(); - - /* Handle default submit */ - const request = new jsOMS.Message.Request.Request(), - self = this; - - request.setData(form.getData()); - request.setType(jsOMS.Message.Response.ResponseType.JSON); - request.setUri(form.getAction()); - request.setMethod(form.getMethod()); - request.setRequestHeader('Content-Type', 'application/json'); - request.setSuccess(function (xhr) + for (let i = 0; i < length; ++i) { + submits[i].addEventListener('click', function (event) { - console.log(xhr.response); + jsOMS.preventAll(event); + self.submit(self.forms[id]); + }); + } + }; - try { - const o = JSON.parse(xhr.response), - response = new jsOMS.Message.Response.Response(o); - let successInject = null; + /** + * Unbind form + * + * @param {string} id Form Id + * + * @return {boolean} + * + * @since 1.0.0 + */ + unbindForm (id) + { + // todo: do i need the findex? can't i just use id? + let findex = 0; - if ((successInject = form.getSuccess()) !== null) { - successInject(response); - } else if (typeof response.get(0) !== 'undefined' && typeof response.get(0).type !== 'undefined') { - // todo: am i using this now and should all cases be handled with the successInjection? - // maybe there could be global response actions where injecting them to every form would not make any sense - // however not many if any use cases come to mind right now where this would be necessary - self.app.responseManager.run(response.get(0).type, response.get(0), request); - } else if (typeof o.status !== 'undefined') { - self.app.notifyManager.send( - new jsOMS.Message.Notification.NotificationMessage(o.status, o.title, o.message), jsOMS.Message.Notification.NotificationType.APP_NOTIFICATION - ); - } - } catch (e) { - console.log(e); + if ((findex = this.forms[id]) !== 'undefined') { + this.forms[id].unbind(); + this.forms.splice(findex, 1); - jsOMS.Log.Logger.instance.error('Invalid form response. \n' - + 'URL: ' + form.getAction() + '\n' - + 'Request: ' + JSON.stringify(form.getData()) + '\n' - + 'Response: ' + xhr.response + return true; + } + + return false; + }; + + /** + * Submit form + * + * Calls injections first befor executing the actual form submit + * + * @param {Object} form Form object + * + * @return {void} + * + * @since 1.0.0 + */ + submit (form) + { + /* Handle injects */ + const self = this, + injects = form.getSubmitInjects(); + let counter = 0; + + // todo: test if attach necessary (maybe already attached in event manager) + // Register normal form behavior + this.app.eventManager.attach(form.getId(), function () + { + self.submitForm(form); + }, true); + + // Run all injects first + for (let property in injects) { + if (injects.hasOwnProperty(property)) { + ++counter; + //this.app.eventManager.addGroup(form.getId(), counter); + const result = injects[property](form, form.getId()); + + if (result === false) { + return; + } + } else { + Logger.instance.warning('Invalid property.'); + } + } + + if (counter < 1) { + this.app.eventManager.trigger(form.getId()); + } + }; + + /** + * Submit form data + * + * Submits the main form data + * + * @param {Object} form Form object + * + * @return {void} + * + * @since 1.0.0 + */ + submitForm (form) + { + if (!form.isValid()) { + this.app.notifyManager.send( + new NotificationMessage(NotificationLevel.INFO, jsOMS.lang.Info, jsOMS.lang.invalid_form), NotificationType.APP_NOTIFICATION + ); + + Logger.instance.debug('Form "' + form.getId() + '" has invalid values.'); + return; + } + + if (form.getMethod() !== RequestMethod.GET + && Math.abs(Date.now() - form.getLastSubmit()) < 500 + ) { + return; + } + + form.updateLastSubmit(); + + /* Handle default submit */ + const request = new Request(), + self = this; + + request.setData(form.getData()); + request.setType(ResponseType.JSON); + request.setUri(form.getAction()); + request.setMethod(form.getMethod()); + request.setRequestHeader('Content-Type', 'application/json'); + request.setSuccess(function (xhr) + { + console.log(xhr.response); + + try { + const o = JSON.parse(xhr.response), + response = new Response(o); + let successInject = null; + + if ((successInject = form.getSuccess()) !== null) { + successInject(response); + } else if (typeof response.get(0) !== 'undefined' && typeof response.get(0).type !== 'undefined') { + // todo: am i using this now and should all cases be handled with the successInjection? + // maybe there could be global response actions where injecting them to every form would not make any sense + // however not many if any use cases come to mind right now where this would be necessary + self.app.responseManager.run(response.get(0).type, response.get(0), request); + } else if (typeof o.status !== 'undefined') { + self.app.notifyManager.send( + new NotificationMessage(o.status, o.title, o.message), NotificationType.APP_NOTIFICATION ); } - }); + } catch (e) { + console.log(e); - request.setResultCallback(0, function (xhr) - { - self.app.notifyManager.send( - new jsOMS.Message.Notification.NotificationMessage( - jsOMS.Message.Notification.NotificationLevel.ERROR, - 'Failure', - 'Some failure happend' - ), jsOMS.Message.Notification.NotificationType.APP_NOTIFICATION + Logger.instance.error('Invalid form response. \n' + + 'URL: ' + form.getAction() + '\n' + + 'Request: ' + JSON.stringify(form.getData()) + '\n' + + 'Response: ' + xhr.response ); - }); - - request.send(); - - if (form.getFinally() !== null) { - form.getFinally()(); } - }; + }); - /** - * Count the bound forms - * - * @return {int} - * - * @since 1.0.0 - */ - count () + request.setResultCallback(0, function (xhr) { - return this.forms.length; - }; - } -}(window.jsOMS = window.jsOMS || {})); + self.app.notifyManager.send( + new NotificationMessage( + NotificationLevel.ERROR, + 'Failure', + 'Some failure happend' + ), NotificationType.APP_NOTIFICATION + ); + }); + + request.send(); + + if (form.getFinally() !== null) { + form.getFinally()(); + } + }; + + /** + * Count the bound forms + * + * @return {int} + * + * @since 1.0.0 + */ + count () + { + return this.forms.length; + }; +}; diff --git a/UI/Component/Input.js b/UI/Component/Input.js index d7d5f52..3f607f5 100644 --- a/UI/Component/Input.js +++ b/UI/Component/Input.js @@ -6,174 +6,166 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class Input { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + this.visObs = null; + }; - /** @namespace jsOMS.UI.Input*/ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input'); + /** + * Unbind input element + * + * @param {Object} input Input element + * + * @return {void} + * + * @since 1.0.0 + */ + static unbind = function (input) + { + this.app.inputManager.getKeyboardManager().unbind(input); + /** global: changeBind */ + input.removeEventListener('change', changeBind, false); + }; - jsOMS.UI.Input = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () + /** + * Bind input element + * + * @param {Object} input Input element + * + * @return {void} + * + * @since 1.0.0 + */ + static bindElement = function (input) + { + if (typeof input === 'undefined') { + throw 'Input element required' + } + + const self = this; + + input.addEventListener('change', function changeBind(event) { - this.visObs = null; - }; - - /** - * Unbind input element - * - * @param {Object} input Input element - * - * @return {void} - * - * @since 1.0.0 - */ - static unbind = function (input) - { - this.app.inputManager.getKeyboardManager().unbind(input); - /** global: changeBind */ - input.removeEventListener('change', changeBind, false); - }; - - /** - * Bind input element - * - * @param {Object} input Input element - * - * @return {void} - * - * @since 1.0.0 - */ - static bindElement = function (input) - { - if (typeof input === 'undefined') { - throw 'Input element required' + console.log('ttttttt'); + /* Handle remote datalist/autocomplete input element */ + let listId, list; + if (typeof (listId = this.getAttribute('list')) !== 'undefined' && (list = document.getElementById(listId)).getAttribute('data-list-src') !== 'undefined') { + self.addRemoteDatalistOptions(this, list); } - const self = this; + /* Handle html defined functions */ + let change; + if (typeof (change = this.getAttribute('data-change-func')) !== 'undefined') { + change(this); + } - input.addEventListener('change', function changeBind(event) + /* Handle pre-defined dynamic change events */ + let ref; + if (typeof (ref = this.getAttribute('data-ref')) !== 'undefined') { + let e = document.getElementById(ref); + + if (!e) { + return; + } + + switch (e.tagName) { + case 'ul': + break; + case 'table': + break; + default: + } + } + }); + + let dataButton; + if (typeof (dataButton = input.getAttribute('data-button')) !== 'undefined') { + this.app.inputManager.getKeyboardManager().bind(input, 13, function () { - console.log('ttttttt'); - /* Handle remote datalist/autocomplete input element */ - let listId, list; - if (typeof (listId = this.getAttribute('list')) !== 'undefined' && (list = document.getElementById(listId)).getAttribute('data-list-src') !== 'undefined') { - self.addRemoteDatalistOptions(this, list); - } + const db = document.getElementById(dataButton); - /* Handle html defined functions */ - let change; - if (typeof (change = this.getAttribute('data-change-func')) !== 'undefined') { - change(this); - } - - /* Handle pre-defined dynamic change events */ - let ref; - if (typeof (ref = this.getAttribute('data-ref')) !== 'undefined') { - let e = document.getElementById(ref); - - if (!e) { - return; - } - - switch (e.tagName) { - case 'ul': - break; - case 'table': - break; - default: - } + if (db) { + db.click(); } }); + } + }; - let dataButton; - if (typeof (dataButton = input.getAttribute('data-button')) !== 'undefined') { - this.app.inputManager.getKeyboardManager().bind(input, 13, function () - { - const db = document.getElementById(dataButton); + /** + * Add remote datalist options + * + * This only applies for datalists that have remote options + * + * @param {Object} input Input element + * @param {Object} datalist Datalist element + * + * @return {void} + * + * @since 1.0.0 + */ + static addRemoteDatalistOptions = function (input, datalist) + { + this.clearDatalistOptions(datalist); - if (db) { - db.click(); - } - }); - } - }; - - /** - * Add remote datalist options - * - * This only applies for datalists that have remote options - * - * @param {Object} input Input element - * @param {Object} datalist Datalist element - * - * @return {void} - * - * @since 1.0.0 - */ - static addRemoteDatalistOptions = function (input, 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) { - this.clearDatalistOptions(datalist); + try { + const o = JSON.parse(xhr.response), + response = new Response(o), + responseLength = response.count(); + let tempResponse = null, + success = null; - const request = new jsOMS.Message.Request(); - request.setData(input.value); - request.setType(jsOMS.Message.Response.ResponseType.JSON); - request.setUri(datalist.getAttribute('data-list-src')); - request.setMethod(jsOMS.Message.Request.RequestMethod.POST); - request.setRequestHeader('Content-Type', 'application/json'); - request.setSuccess(function (xhr) - { - try { - const o = JSON.parse(xhr.response), - response = new jsOMS.Message.Response(o), - responseLength = response.count(); - let tempResponse = null, - success = null; + for (let k = 0; k < responseLength; ++k) { + tempResponse = response.getByIndex(k); - for (let k = 0; k < responseLength; ++k) { - tempResponse = response.getByIndex(k); + let option = null, + data = tempResponse.getData(), + length = data.length; - let option = null, - data = tempResponse.getData(), - length = data.length; + for (let i = 0; i < length; ++i) { + option = document.createElement('option'); + option.value = tempResponse.value; + option.text = tempResponse.text; - for (let i = 0; i < length; ++i) { - option = document.createElement('option'); - option.value = tempResponse.value; - option.text = tempResponse.text; - - datalist.appendChild(option); - } + datalist.appendChild(option); } - } catch (exception) { - jsOMS.Log.Logger.instance.error('Invalid JSON object: ' + xhr, 'FormManager'); } - }); - - request.send(); - }; - - /** - * Remove all datalist options from datalist - * - * @param {Object} datalist Datalist element - * - * @return {void} - * - * @since 1.0.0 - */ - static clearDatalistOptions = function (datalist) - { - const length = datalist.options.length; - - for (let i = 0; i < length; ++i) { - datalist.remove(0); + } catch (exception) { + Logger.instance.error('Invalid JSON object: ' + xhr, 'FormManager'); } - }; - } -}(window.jsOMS = window.jsOMS || {})); + }); + + request.send(); + }; + + /** + * Remove all datalist options from datalist + * + * @param {Object} datalist Datalist element + * + * @return {void} + * + * @since 1.0.0 + */ + static clearDatalistOptions = function (datalist) + { + const length = datalist.options.length; + + for (let i = 0; i < length; ++i) { + datalist.remove(0); + } + }; +}; diff --git a/UI/Component/Tab.js b/UI/Component/Tab.js index ab1e102..a5e772f 100644 --- a/UI/Component/Tab.js +++ b/UI/Component/Tab.js @@ -1,3 +1,6 @@ +import { UriFactory } from '../../Uri/UriFactory.js'; +import { Http } from '../../Uri/Http.js'; + /** * Tab manager class. * @@ -6,133 +9,126 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class Tab { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor (app) + { + this.app = app; + }; - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Component'); + /** + * Bind & rebind UI elements. + * + * @param {string} [id] Element id + * + * @return {void} + * + * @since 1.0.0 + */ + bind (id) + { + if (typeof id !== 'undefined') { + const e = document.getElementById(id); - jsOMS.UI.Component.Tab = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor (app) - { - this.app = app; - }; - - /** - * Bind & rebind UI elements. - * - * @param {string} [id] Element id - * - * @return {void} - * - * @since 1.0.0 - */ - bind (id) - { - if (typeof id !== 'undefined') { - const e = document.getElementById(id); - - if (e) { - this.bindElement(e); - } - } else { - const tabs = document.getElementsByClassName('tabview'), - length = !tabs ? 0 : tabs.length; - - for (let i = 0; i < length; ++i) { - this.bindElement(tabs[i]); - } + if (e) { + this.bindElement(e); } - }; - - /** - * Bind & rebind UI element. - * - * @param {Object} e Element - * - * @return {void} - * - * @since 1.0.0 - */ - bindElement (e) - { - const nodes = e.querySelectorAll('.tab-links li'), - length = nodes.length; + } else { + const tabs = document.getElementsByClassName('tabview'), + length = !tabs ? 0 : tabs.length; for (let i = 0; i < length; ++i) { - nodes[i].addEventListener('click', function (evt) - { - let fragmentString = window.location.href.includes('#') ? jsOMS.Uri.Http.parseUrl(window.location.href).fragment : ''; + this.bindElement(tabs[i]); + } + } + }; - /* Change Tab */ - /* Remove selected tab */ - const oldActive = this.parentNode.getElementsByClassName('active'); - if (oldActive.length > 0) { - // find old active and remove it - fragmentString = jsOMS.trim( - fragmentString.replace(oldActive[0].getElementsByTagName('label')[0].getAttribute('for'), ''), - ',' - ); + /** + * Bind & rebind UI element. + * + * @param {Object} e Element + * + * @return {void} + * + * @since 1.0.0 + */ + bindElement (e) + { + const nodes = e.querySelectorAll('.tab-links li'), + length = nodes.length; - jsOMS.removeClass(oldActive[0], 'active'); - } + for (let i = 0; i < length; ++i) { + nodes[i].addEventListener('click', function (evt) + { + let fragmentString = window.location.href.includes('#') ? Http.parseUrl(window.location.href).fragment : ''; - // remove new element if new element already inside, alternatively check for existence and don't do a new push state? - // todo: here is a bug or in the uri factory. replace also replaces substrings e.g. #test-c-tab-1 gets partially replaced - // by c-tab-1. either search for #c-tab-1 or ,c-tab-1 to be certain. That's not possible because it doesn't start with `#` + /* Change Tab */ + /* Remove selected tab */ + const oldActive = this.parentNode.getElementsByClassName('active'); + if (oldActive.length > 0) { + // find old active and remove it fragmentString = jsOMS.trim( - fragmentString.replace(this.getElementsByTagName('label')[0].getAttribute('for'), ''), + fragmentString.replace(oldActive[0].getElementsByTagName('label')[0].getAttribute('for'), ''), ',' ); - jsOMS.addClass(this, 'active'); + jsOMS.removeClass(oldActive[0], 'active'); + } - /* Add selected tab */ - window.history.pushState(null, '', - jsOMS.Uri.UriFactory.build( - '{%}#' + (fragmentString === '' ? '' : fragmentString + ',') + this.getElementsByTagName('label')[0].getAttribute('for') - ) - ); - }); - } + // remove new element if new element already inside, alternatively check for existence and don't do a new push state? + // todo: here is a bug or in the uri factory. replace also replaces substrings e.g. #test-c-tab-1 gets partially replaced + // by c-tab-1. either search for #c-tab-1 or ,c-tab-1 to be certain. That's not possible because it doesn't start with `#` + fragmentString = jsOMS.trim( + fragmentString.replace(this.getElementsByTagName('label')[0].getAttribute('for'), ''), + ',' + ); - this.activateTabUri(e); - }; + jsOMS.addClass(this, 'active'); - /** - * Activates the correct tab based on URI fragment. - * - * This allows to link a specific open tab to a user or make it a bookmark - * - * @param {Object} e Element - * - * @return {void} - * - * @since 1.0.0 - */ - activateTabUri(e) - { - const fragmentString = window.location.href.includes('#') ? jsOMS.Uri.Http.parseUrl(window.location.href).fragment : ''; - const fragments = fragmentString.split(','), - fragLength = fragments.length; + /* Add selected tab */ + window.history.pushState(null, '', + UriFactory.build( + '{%}#' + (fragmentString === '' ? '' : fragmentString + ',') + this.getElementsByTagName('label')[0].getAttribute('for') + ) + ); + }); + } - if (fragLength > 0 && fragmentString !== '') { - for (let i = 0; i < fragLength; ++i) { - let label = e.querySelectorAll('label[for="' + fragments[i] + '"]')[0]; - if (typeof label !== 'undefined') { - label.click(); - } + this.activateTabUri(e); + }; + + /** + * Activates the correct tab based on URI fragment. + * + * This allows to link a specific open tab to a user or make it a bookmark + * + * @param {Object} e Element + * + * @return {void} + * + * @since 1.0.0 + */ + activateTabUri(e) + { + const fragmentString = window.location.href.includes('#') ? Http.parseUrl(window.location.href).fragment : ''; + const fragments = fragmentString.split(','), + fragLength = fragments.length; + + if (fragLength > 0 && fragmentString !== '') { + for (let i = 0; i < fragLength; ++i) { + let label = e.querySelectorAll('label[for="' + fragments[i] + '"]')[0]; + if (typeof label !== 'undefined') { + label.click(); } } + } - if (e.getElementsByClassName('active').length < 1) { - e.querySelector('label').click(); - } - }; - } -}(window.jsOMS = window.jsOMS || {})); + if (e.getElementsByClassName('active').length < 1) { + e.querySelector('label').click(); + } + }; +}; diff --git a/UI/Component/Table.js b/UI/Component/Table.js index 5296514..e740029 100644 --- a/UI/Component/Table.js +++ b/UI/Component/Table.js @@ -1,3 +1,6 @@ +import { TableView } from '../../Views/TableView.js'; +import { Request } from '../../Message/Request/Request.js'; +import { ResponseType } from '../../Message/Response/ResponseType.js'; /** * Table manager class. * @@ -6,454 +9,580 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class Table { + /** + * @constructor + * + * @param {Object} app Application + * + * @since 1.0.0 + */ + constructor(app) + { + this.app = app; + this.tables = {}; + this.ignore = {}; + }; - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Component'); + /** + * Bind & rebind UI elements. + * + * @param {string} [id] Element id + * + * @return {void} + * + * @since 1.0.0 + */ + bind (id) + { + if (typeof id !== 'undefined' && typeof this.ignore[id] === 'undefined') { + this.bindTable(id); + } else { + const tables = document.getElementsByTagName('table'), + length = !tables ? 0 : tables.length; - jsOMS.UI.Component.Table = class { - /** - * @constructor - * - * @param {Object} app Application - * - * @since 1.0.0 - */ - constructor(app) - { - this.app = app; - this.tables = {}; - this.ignore = {}; - }; - - /** - * Bind & rebind UI elements. - * - * @param {string} [id] Element id - * - * @return {void} - * - * @since 1.0.0 - */ - bind (id) - { - if (typeof id !== 'undefined' && typeof this.ignore[id] === 'undefined') { - this.bindTable(id); - } else { - const tables = document.getElementsByTagName('table'), - length = !tables ? 0 : tables.length; - - for (let i = 0; i < length; ++i) { - let tableId = tables[i].getAttribute('id'); - if (typeof tableId !== 'undefined' && tableId !== null && typeof this.ignore[tableId] === 'undefined') { - this.bindTable(tableId); - } + for (let i = 0; i < length; ++i) { + let tableId = tables[i].getAttribute('id'); + if (typeof tableId !== 'undefined' && tableId !== null && typeof this.ignore[tableId] === 'undefined') { + this.bindTable(tableId); } } - }; + } + }; - /** - * Unbind table - * - * @param {string} id Table Id - * - * @return {void} - * - * @since 1.0.0 - */ - unbind (id) + /** + * Unbind table + * + * @param {string} id Table Id + * + * @return {void} + * + * @since 1.0.0 + */ + unbind (id) + { + + }; + + /** + * Bind & rebind UI element. + * + * @param {Object} [id] Element id + * + * @return {void} + * + * @since 1.0.0 + */ + bindTable (id) + { + if (typeof id === 'undefined' || !id) { + jsOMS.Log.Logger.instance.info('A table doesn\'t have an ID.'); + return; + } + + this.tables[id] = new TableView(id); + + this.unbind(id); + + this.bindExport(this.tables[id]); + + // todo: sorting: increasing / decreasing only if icons are available + // todo: filtering: equals (alphanumeric), greater, greater equals, lesser, lesser equals, contains, doesn't contain, excel like selection of elements. Amount of filtering options unlimited. + // cell value should be data-value="" and cell name should be data-name="" and cell content should be data-content="". + // if no value is defined than data-value = cell content. if no name is defined then data-name = cell content. if no content is defined then data-content = cell content. + + const sorting = this.tables[id].getSorting(); + let length = sorting.length; + for (let i = 0; i < length; ++i) { + this.bindSorting(sorting[i], id); + } + + const order = this.tables[id].getSortableRows(); + length = order.length; + for (let i = 0; i < length; ++i) { + this.bindReorder(order[i], id); + } + + const filters = this.tables[id].getFilter(); + length = filters.length; + for (let i = 0; i < length; ++i) { + this.bindFiltering(filters[i], id); + } + + const removable = this.tables[id].getRemovable(); + length = removable.length; + for (let i = 0; i < length; ++i) { + this.bindRemovable(removable[i], id); + } + + const createForm = this.tables[id].getForm(); + const createButton = document.getElementById(id).getAttribute('data-table-add'); + + if (createButton !== null) { + this.bindCreateInline(createButton, id); + } else if (createForm !== null) { + this.bindCreateForm(createForm, id); + } + + const update = this.tables[id].getUpdatable(); + length = update.length; + for (let i = 0; i < length; ++i) { + this.bindUpdatable(update[i], id); + } + }; + + /** + * Export a table + * + * @param {Element} exports Export button + * + * @return {void} + * + * @since 1.0.0 + */ + bindExport(exports) + { + const button = exports.getExport(); + + if (typeof button === 'undefined' || button === null) { + return; + } + + button.addEventListener('click', function (event) { + console.log(exports.serialize()); + // todo: either create download in javascript from this data or make roundtrip to server who then sends the data + // - think about allowing different export formats (json, csv, excel) + // - maybe this should never be done from the ui, maybe a endpoint uri should be specified which then calls the api get function for this data + }); + }; - }; + /** + * Removes the closest row on click. + * + * @param {Element} remove Remove button + * @param {Object} id Element id + * + * @return {void} + * + * @since 1.0.0 + */ + bindRemovable(remove, id) + { + if (remove.closest('form').getAttribute('method') !== 'NONE') { + this.app.uiManager.getFormManager().get(remove.closest('form').id).setSuccess(function () { + document.getElementById(id).deleteRow(remove.closest('tr').rowIndex); + }); + } else { + this.app.uiManager.getFormManager().get(remove.closest('form').id).setFinally(function () { + document.getElementById(id).deleteRow(remove.closest('tr').rowIndex); + }); + } + }; - /** - * Bind & rebind UI element. - * - * @param {Object} [id] Element id - * - * @return {void} - * - * @since 1.0.0 - */ - bindTable (id) + /** + * Swaps the row on click. + * + * @param {Element} sorting Swap button + * @param {Object} id Element id + * + * @return {void} + * + * @since 1.0.0 + */ + bindReorder(sorting, id) + { + sorting.addEventListener('click', function (event) { - if (typeof id === 'undefined' || !id) { - jsOMS.Log.Logger.instance.info('A table doesn\'t have an ID.'); + jsOMS.preventAll(event); + + const table = document.getElementById(id), + rows = table.getElementsByTagName('tbody')[0].rows, + rowLength = rows.length, + rowId = this.closest('tr').rowIndex, + orderType = jsOMS.hasClass(this, 'order-up') ? 1 : -1; + + + if (orderType === 1 && rowId > 1) { + rows[rowId].parentNode.insertBefore(rows[rowId - 2], rows[rowId]); + } else if (orderType === -1 && rowId < rowLength) { + rows[rowId - 1].parentNode.insertBefore(rows[rowId], rows[rowId - 1]); + } + + // todo: submit new order to remote + }); + }; + + /** + * Sorts the table. + * + * @param {Element} sorting Sort button + * @param {Object} id Table id + * + * @return {void} + * + * @since 1.0.0 + */ + bindSorting(sorting, id) + { + sorting.addEventListener('click', function (event) + { + jsOMS.preventAll(event); + + const table = document.getElementById(id), + rows = table.getElementsByTagName('tbody')[0].rows, + rowLength = rows.length, + cellId = this.closest('td').cellIndex, + sortType = jsOMS.hasClass(this, 'sort-asc') ? 1 : -1; + + let j, i, row1, row2, content1, content2, + order = false, + shouldSwitch = false; + + const columnName = this.closest('td').getAttribute('data-name'); + + table.setAttribute('data-sorting', (sortType > 0 ? '+' : '-') + (columnName !== null ? columnName : cellId)); + + if (table.getAttribute('data-src') !== null) { + Table.getRemoteData(table); return; } - this.tables[id] = new jsOMS.Views.TableView(id); + do { + order = false; - this.unbind(id); - - this.bindExport(this.tables[id]); - - // todo: sorting: increasing / decreasing only if icons are available - // todo: filtering: equals (alphanumeric), greater, greater equals, lesser, lesser equals, contains, doesn't contain, excel like selection of elements. Amount of filtering options unlimited. - // cell value should be data-value="" and cell name should be data-name="" and cell content should be data-content="". - // if no value is defined than data-value = cell content. if no name is defined then data-name = cell content. if no content is defined then data-content = cell content. - - const sorting = this.tables[id].getSorting(); - let length = sorting.length; - for (let i = 0; i < length; ++i) { - this.bindSorting(sorting[i], id); - } - - const order = this.tables[id].getSortableRows(); - length = order.length; - for (let i = 0; i < length; ++i) { - this.bindReorder(order[i], id); - } - - const filters = this.tables[id].getFilter(); - length = filters.length; - for (let i = 0; i < length; ++i) { - this.bindFiltering(filters[i], id); - } - - const removable = this.tables[id].getRemovable(); - length = removable.length; - for (let i = 0; i < length; ++i) { - this.bindRemovable(removable[i], id); - } - - const createForm = this.tables[id].getForm(); - const createButton = document.getElementById(id).getAttribute('data-table-add'); - - if (createButton !== null) { - this.bindCreateInline(createButton, id); - } else if (createForm !== null) { - this.bindCreateForm(createForm, id); - } - - const update = this.tables[id].getUpdatable(); - length = update.length; - for (let i = 0; i < length; ++i) { - this.bindUpdatable(update[i], id); - } - }; - - /** - * Export a table - * - * @param {Element} exports Export button - * - * @return {void} - * - * @since 1.0.0 - */ - bindExport(exports) - { - const button = exports.getExport(); - - if (typeof button === 'undefined' || button === null) { - return; - } - - button.addEventListener('click', function (event) - { - console.log(exports.serialize()); - // todo: either create download in javascript from this data or make roundtrip to server who then sends the data - // - think about allowing different export formats (json, csv, excel) - // - maybe this should never be done from the ui, maybe a endpoint uri should be specified which then calls the api get function for this data - }); - }; - - /** - * Removes the closest row on click. - * - * @param {Element} remove Remove button - * @param {Object} id Element id - * - * @return {void} - * - * @since 1.0.0 - */ - bindRemovable(remove, id) - { - if (remove.closest('form').getAttribute('method') !== 'NONE') { - this.app.uiManager.getFormManager().get(remove.closest('form').id).setSuccess(function () { - document.getElementById(id).deleteRow(remove.closest('tr').rowIndex); - }); - } else { - this.app.uiManager.getFormManager().get(remove.closest('form').id).setFinally(function () { - document.getElementById(id).deleteRow(remove.closest('tr').rowIndex); - }); - } - }; - - /** - * Swaps the row on click. - * - * @param {Element} sorting Swap button - * @param {Object} id Element id - * - * @return {void} - * - * @since 1.0.0 - */ - bindReorder(sorting, id) - { - sorting.addEventListener('click', function (event) - { - jsOMS.preventAll(event); - - const table = document.getElementById(id), - rows = table.getElementsByTagName('tbody')[0].rows, - rowLength = rows.length, - rowId = this.closest('tr').rowIndex, - orderType = jsOMS.hasClass(this, 'order-up') ? 1 : -1; - - - if (orderType === 1 && rowId > 1) { - rows[rowId].parentNode.insertBefore(rows[rowId - 2], rows[rowId]); - } else if (orderType === -1 && rowId < rowLength) { - rows[rowId - 1].parentNode.insertBefore(rows[rowId], rows[rowId - 1]); - } - - // todo: submit new order to remote - }); - }; - - /** - * Sorts the table. - * - * @param {Element} sorting Sort button - * @param {Object} id Table id - * - * @return {void} - * - * @since 1.0.0 - */ - bindSorting(sorting, id) - { - sorting.addEventListener('click', function (event) - { - jsOMS.preventAll(event); - - const table = document.getElementById(id), - rows = table.getElementsByTagName('tbody')[0].rows, - rowLength = rows.length, - cellId = this.closest('td').cellIndex, - sortType = jsOMS.hasClass(this, 'sort-asc') ? 1 : -1; - - let j, i, row1, row2, content1, content2, - order = false, + for (j = 0; j < rowLength - 1; ++j) { shouldSwitch = false; + row1 = rows[j].getElementsByTagName('td')[cellId]; + content1 = row1.getAttribute('data-content') !== null ? row1.getAttribute('data-content') : row1.textContent; - const columnName = this.closest('td').getAttribute('data-name'); + for (i = j + 1; i < rowLength; ++i) { + row2 = rows[i].getElementsByTagName('td')[cellId]; + content2 = row2.getAttribute('data-content') !== null ? row2.getAttribute('data-content') : row2.textContent; - table.setAttribute('data-sorting', (sortType > 0 ? '+' : '-') + (columnName !== null ? columnName : cellId)); - - if (table.getAttribute('data-src') !== null) { - jsOMS.UI.Component.Table.getRemoteData(table); - return; - } - - do { - order = false; - - for (j = 0; j < rowLength - 1; ++j) { - shouldSwitch = false; - row1 = rows[j].getElementsByTagName('td')[cellId]; - content1 = row1.getAttribute('data-content') !== null ? row1.getAttribute('data-content') : row1.textContent; - - for (i = j + 1; i < rowLength; ++i) { - row2 = rows[i].getElementsByTagName('td')[cellId]; - content2 = row2.getAttribute('data-content') !== null ? row2.getAttribute('data-content') : row2.textContent; - - if (sortType === 1 && content1 > content2) { - shouldSwitch = true; - } else if (sortType === -1 && content1 < content2) { - shouldSwitch = true; - } else { - break; - } - } - - if (shouldSwitch === true) { + if (sortType === 1 && content1 > content2) { + shouldSwitch = true; + } else if (sortType === -1 && content1 < content2) { + shouldSwitch = true; + } else { break; } } - if (shouldSwitch) { - rows[j].parentNode.insertBefore(rows[i - 1], rows[j]); - order = true; + if (shouldSwitch === true) { + break; } - } while (order); - }); - }; + } - /** - * Filters the table. - * - * @param {Element} filtering Filter button - * @param {Object} id Table id - * - * @return {void} - * - * @since 1.0.0 - */ - bindFiltering(filtering, id) + if (shouldSwitch) { + rows[j].parentNode.insertBefore(rows[i - 1], rows[j]); + order = true; + } + } while (order); + }); + }; + + /** + * Filters the table. + * + * @param {Element} filtering Filter button + * @param {Object} id Table id + * + * @return {void} + * + * @since 1.0.0 + */ + bindFiltering(filtering, id) + { + filtering.addEventListener('click', function (event) { - filtering.addEventListener('click', function (event) - { + jsOMS.preventAll(event); + + const tpl = document.getElementById('table-filter-tpl'); + + if (tpl === null || document.getElementById(tpl.content.firstElementChild.id) !== null) { + return; + } + + const posY = event.pageY + document.body.scrollTop + document.documentElement.scrollTop + tpl.parentNode.scrollTop - tpl.parentNode.getBoundingClientRect().top; + const posX = event.pageX + document.body.scrollLeft + document.documentElement.scrollLeft + tpl.parentNode.scrollLeft - tpl.parentNode.getBoundingClientRect().left; + + const output = document.importNode(tpl.content, true); + output.firstElementChild.setAttribute('style', 'position: absolute; top: ' + posY + 'px; left: ' + posX + 'px;') + output.firstElementChild.setAttribute('data-table', this.closest('table').id); + output.firstElementChild.setAttribute('data-table-column', this.closest('td').cellIndex); + + // todo: set existing filtering option in ui here + + // todo: do this as injection into a form instead? -this would require cleanup for the events every time + output.firstElementChild.querySelectorAll('button[type="submit"], input[type="submit"]')[0].addEventListener('click', function (event) { jsOMS.preventAll(event); - const tpl = document.getElementById('table-filter-tpl'); + const input = document.getElementById('table-filter').querySelectorAll('input, select'); + const length = input.length; - if (tpl === null || document.getElementById(tpl.content.firstElementChild.id) !== null) { + let filter = []; + + for (let i = 0; i < length; ++i) { + filter.push(input[i].value); + } + + const table = document.getElementById(document.getElementById('table-filter').getAttribute('data-table')); + + table.querySelectorAll('thead td')[ + document.getElementById('table-filter').getAttribute('data-table-column') + ].setAttribute('data-filter', JSON.stringify(filter)); + + // todo: if not empty highlight filter button for user indication that filter is active + // todo: filter locally and if src is available to remote filter maybe just create an apply function which calls the different functions? + + document.getElementById('table-filter').parentNode.removeChild(document.getElementById('table-filter')); + + if (table.getAttribute('data-src') !== null) { + Table.getRemoteData(table); return; } - const posY = event.pageY + document.body.scrollTop + document.documentElement.scrollTop + tpl.parentNode.scrollTop - tpl.parentNode.getBoundingClientRect().top; - const posX = event.pageX + document.body.scrollLeft + document.documentElement.scrollLeft + tpl.parentNode.scrollLeft - tpl.parentNode.getBoundingClientRect().left; - - const output = document.importNode(tpl.content, true); - output.firstElementChild.setAttribute('style', 'position: absolute; top: ' + posY + 'px; left: ' + posX + 'px;') - output.firstElementChild.setAttribute('data-table', this.closest('table').id); - output.firstElementChild.setAttribute('data-table-column', this.closest('td').cellIndex); - - // todo: set existing filtering option in ui here - - // todo: do this as injection into a form instead? -this would require cleanup for the events every time - output.firstElementChild.querySelectorAll('button[type="submit"], input[type="submit"]')[0].addEventListener('click', function (event) { - jsOMS.preventAll(event); - - const input = document.getElementById('table-filter').querySelectorAll('input, select'); - const length = input.length; - - let filter = []; - - for (let i = 0; i < length; ++i) { - filter.push(input[i].value); - } - - const table = document.getElementById(document.getElementById('table-filter').getAttribute('data-table')); - - table.querySelectorAll('thead td')[ - document.getElementById('table-filter').getAttribute('data-table-column') - ].setAttribute('data-filter', JSON.stringify(filter)); - - // todo: if not empty highlight filter button for user indication that filter is active - // todo: filter locally and if src is available to remote filter maybe just create an apply function which calls the different functions? - - document.getElementById('table-filter').parentNode.removeChild(document.getElementById('table-filter')); - - if (table.getAttribute('data-src') !== null) { - jsOMS.UI.Component.Table.getRemoteData(table); - return; - } - - // todo: implement local filtering if no data-src available - }); - - output.firstElementChild.querySelectorAll('button[type="reset"], input[type="reset"]')[0].addEventListener('click', function (event) { - document.getElementById('table-filter').parentNode.removeChild(document.getElementById('table-filter')); - }); - - tpl.parentNode.appendChild(output); + // todo: implement local filtering if no data-src available }); + + output.firstElementChild.querySelectorAll('button[type="reset"], input[type="reset"]')[0].addEventListener('click', function (event) { + document.getElementById('table-filter').parentNode.removeChild(document.getElementById('table-filter')); + }); + + tpl.parentNode.appendChild(output); + }); + }; + + /** + * Create the table row + * + * @param {string} createForm Create form + * @param {Object} id Table id + * + * @return {void} + * + * @since 1.0.0 + */ + bindCreateForm(createForm, id) + { + this.app.uiManager.getFormManager().get(createForm).injectSubmit(function () { + const table = document.getElementById(id).getElementsByTagName('tbody')[0]; + const newRow = table.getElementsByTagName('template')[0].content.cloneNode(true); + + // set internal value + let fields = newRow.querySelectorAll('[data-tpl-value]'); + let fieldLength = fields.length; + let uuid = ''; + let value = ''; + + for (let j = 0; j < fieldLength; ++j) { + value = document.querySelectorAll( + '#' + createForm + ' [data-tpl-value="' + fields[j].getAttribute('data-tpl-value') + '"], [data-form="' + createForm + '"][data-tpl-value="' + fields[j].getAttribute('data-tpl-value') + '"]')[0] + .getAttribute('data-value'); + + // todo: we need to check what kind of tag the selector above returns in order to get the correct value. currently this only makes sense for input elements but for selection, checkboxes etc. this doesn't make sense there we need .innerHtml or [data-text=] + + fields[j].setAttribute('data-value', value); + + uuid += value; + } + + // don't allow duplicate + if (table.querySelectorAll('[data-tpl-uuid="' + uuid + '"').length !== 0) { + return; + } + + newRow.firstElementChild.setAttribute('data-tpl-uuid', uuid); + + // set readable text + fields = newRow.querySelectorAll('[data-tpl-text]'); + fieldLength = fields.length; + + for (let j = 0; j < fieldLength; ++j) { + fields[j].appendChild( + document.createTextNode( + document.querySelectorAll('#' + createForm + ' [data-tpl-text="' + fields[j].getAttribute('data-tpl-text') + '"], [data-form="' + createForm + '"][data-tpl-text="' + fields[j].getAttribute('data-tpl-text') + '"]')[0].value + ) + ); + + // todo: we need to check what kind of tag the selector above returns in order to get the correct value. currently this only makes sense for input elements but for selection, checkboxes etc. this doesn't make sense there we need .innerHtml or [data-text=] + } + + table.appendChild(newRow); + // todo: consider to do ui action as success inject to the backend request... maybe optional because sometimes there will be no backend call? + // todo: if a column has a form in the template the id of the form needs to be set unique somehow (e.g. remove button in form) + + // todo: bind removable + // todo: bind edit + + return true; + }); + }; + + /** + * Create the table row + * + * @param {string} createForm Create form + * @param {Object} id Table id + * + * @return {void} + * + * @since 1.0.0 + */ + bindCreateInline(createForm, id) + { + const self = this; + + document.getElementById(createForm).addEventListener('click', function() { + const table = document.getElementById(id).getElementsByTagName('tbody')[0]; + const newRow = table.getElementsByTagName('template')[1].content.cloneNode(true); + const rowId = 'f' + Math.random().toString(36).substring(7); + // todo: check if random id doesn't already exist + + newRow.firstElementChild.id = rowId; + newRow.firstElementChild.getElementsByTagName('form')[0].id = rowId + '-form'; + + const fields = newRow.firstElementChild.querySelectorAll('[data-form="' + self.tables[id].getForm() + '"]'); + const length = fields.length; + + for (let i = 0; i < length; ++i) { + fields[i].setAttribute('data-form', rowId + '-form'); + } + + table.appendChild(newRow.firstElementChild); + + self.bindCreateForm(rowId + '-form', id); + self.app.uiManager.getFormManager().get(rowId + '-form').injectSubmit(function () { + document.getElementById(id).getElementsByTagName('tbody')[0].removeChild( + document.getElementById(rowId) + ); + }); + + // todo: bind removable + // todo: bind edit + }); + + // todo: this is polluting the form manager because it should be emptied afterwards (form is deleted but not from form manager) + // todo: consider to do ui action as success inject to the backend request... maybe optional because sometimes there will be no backend call? + // todo: if a column has a form in the template the id of the form needs to be set unique somehow (e.g. remove button in form) + }; + + static getRemoteData (table) + { + const data = { + limit: table.getAttribute('data-limit'), + offset: table.getAttribute('data-offset'), + sorting: table.getAttribute('data-sorting'), + filter: table.getAttribute('data-filter') }; - /** - * Create the table row - * - * @param {string} createForm Create form - * @param {Object} id Table id - * - * @return {void} - * - * @since 1.0.0 - */ - bindCreateForm(createForm, id) - { - this.app.uiManager.getFormManager().get(createForm).injectSubmit(function () { - const table = document.getElementById(id).getElementsByTagName('tbody')[0]; - const newRow = table.getElementsByTagName('template')[0].content.cloneNode(true); + const request = new Request(); + request.setData(data); + request.setType(ResponseType.JSON); + request.setUri(table.getAttribute('data-src')); + request.setMethod('GET'); + request.setRequestHeader('Content-Type', 'application/json'); + request.setSuccess(function (xhr) { + Table.emptyTable(table.getElementsByTagName('tbody')[0]); + Table.addToTable(table.getElementsByTagName('tbody')[0], JSON.parse(xhr.response)); + }); - // set internal value - let fields = newRow.querySelectorAll('[data-tpl-value]'); - let fieldLength = fields.length; - let uuid = ''; - let value = ''; + request.send(); + }; - for (let j = 0; j < fieldLength; ++j) { - value = document.querySelectorAll( - '#' + createForm + ' [data-tpl-value="' + fields[j].getAttribute('data-tpl-value') + '"], [data-form="' + createForm + '"][data-tpl-value="' + fields[j].getAttribute('data-tpl-value') + '"]')[0] - .getAttribute('data-value'); + static emptyTable(table) + { + const rows = table.getElementsByTagName('tr'); + const length = rows.length; - // todo: we need to check what kind of tag the selector above returns in order to get the correct value. currently this only makes sense for input elements but for selection, checkboxes etc. this doesn't make sense there we need .innerHtml or [data-text=] + for (let i = 0; i < length; ++i) { + rows[i].parentNode.removeChild(rows[i]); + } + }; - fields[j].setAttribute('data-value', value); + static addToTable(table, data) + { + const dataLength = data.length; - uuid += value; - } + console.table(data); - // don't allow duplicate - if (table.querySelectorAll('[data-tpl-uuid="' + uuid + '"').length !== 0) { - return; - } + for (let i = 0; i < dataLength; ++i) { + // set readable value + const newRow = table.getElementsByTagName('template')[0].content.cloneNode(true); + let fields = newRow.querySelectorAll('[data-tpl-text]'); + let fieldLength = fields.length; - newRow.firstElementChild.setAttribute('data-tpl-uuid', uuid); + for (let j = 0; j < fieldLength; ++j) { + fields[j].appendChild( + document.createTextNode( + jsOMS.getArray(fields[j].getAttribute('data-tpl-text'), data[i]) + ) + ); + } - // set readable text - fields = newRow.querySelectorAll('[data-tpl-text]'); - fieldLength = fields.length; + // set internal value + fields = newRow.querySelectorAll('[data-tpl-value]'); + fieldLength = fields.length; - for (let j = 0; j < fieldLength; ++j) { - fields[j].appendChild( - document.createTextNode( - document.querySelectorAll('#' + createForm + ' [data-tpl-text="' + fields[j].getAttribute('data-tpl-text') + '"], [data-form="' + createForm + '"][data-tpl-text="' + fields[j].getAttribute('data-tpl-text') + '"]')[0].value - ) - ); + for (let j = 0; j < fieldLength; ++j) { + fields[j].setAttribute( + 'data-value', + jsOMS.getArray(fields[j].getAttribute('data-tpl-value'), data[i]) + ); + } - // todo: we need to check what kind of tag the selector above returns in order to get the correct value. currently this only makes sense for input elements but for selection, checkboxes etc. this doesn't make sense there we need .innerHtml or [data-text=] - } + table.appendChild(newRow); - table.appendChild(newRow); - // todo: consider to do ui action as success inject to the backend request... maybe optional because sometimes there will be no backend call? - // todo: if a column has a form in the template the id of the form needs to be set unique somehow (e.g. remove button in form) + // todo: bind buttons if required (e.g. remove, edit button) + } + }; - // todo: bind removable - // todo: bind edit + bindUpdatable (update, id) + { + const self = this; - return true; - }); - }; + update.addEventListener('click', function() { + // handle external form + // handle internal form + const formId = document.getElementById(id).getAttribute('data-table-form'); + const values = this.closest('tr').querySelectorAll('[data-tpl-value]'); + const text = this.closest('tr').querySelectorAll('[data-tpl-text]'); + const table = document.getElementById(id).getElementsByTagName('tbody')[0]; - /** - * Create the table row - * - * @param {string} createForm Create form - * @param {Object} id Table id - * - * @return {void} - * - * @since 1.0.0 - */ - bindCreateInline(createForm, id) - { - const self = this; + if (document.getElementById(formId) === null) { + this.closest('tr').style = "display: none"; // todo: replace with class instead of inline style - document.getElementById(createForm).addEventListener('click', function() { - const table = document.getElementById(id).getElementsByTagName('tbody')[0]; const newRow = table.getElementsByTagName('template')[1].content.cloneNode(true); const rowId = 'f' + Math.random().toString(36).substring(7); - // todo: check if random id doesn't already exist + // todo: don't use random ide use actual row id for data which needs to be updated newRow.firstElementChild.id = rowId; newRow.firstElementChild.getElementsByTagName('form')[0].id = rowId + '-form'; const fields = newRow.firstElementChild.querySelectorAll('[data-form="' + self.tables[id].getForm() + '"]'); - const length = fields.length; + let length = fields.length; for (let i = 0; i < length; ++i) { fields[i].setAttribute('data-form', rowId + '-form'); } - table.appendChild(newRow.firstElementChild); + // insert row values data into form + length = values.length; + for (let i = 0; i < length; ++i) { + newRow.firstElementChild.querySelectorAll('[data-tpl-value="' + values[i].getAttribute('data-tpl-value') + '"')[0].value = values[i].value; + // todo: handle different input types + } + + // insert row text data into form + length = text.length; + for (let i = 0; i < length; ++i) { + newRow.firstElementChild.querySelectorAll('[data-tpl-text="' + text[i].getAttribute('data-tpl-text') + '"')[0].value = text[i].innerText; + console.log(text[i].innerText); + // todo: handle different input types + } + + table.insertBefore(newRow.firstElementChild, this.closest('tr')); self.bindCreateForm(rowId + '-form', id); self.app.uiManager.getFormManager().get(rowId + '-form').injectSubmit(function () { @@ -462,168 +591,35 @@ ); }); - // todo: bind removable - // todo: bind edit - }); + // todo: replace add button with save button and add cancel button + // todo: on save button click insert data into hidden row and show hidden row again, delete form row + } else { + const fields = document.getElementById(formId).querySelectorAll('[data-form="' + self.tables[id].getForm() + '"]'); + let length = fields.length; - // todo: this is polluting the form manager because it should be emptied afterwards (form is deleted but not from form manager) - // todo: consider to do ui action as success inject to the backend request... maybe optional because sometimes there will be no backend call? - // todo: if a column has a form in the template the id of the form needs to be set unique somehow (e.g. remove button in form) - }; + for (let i = 0; i < length; ++i) { + fields[i].setAttribute('data-form', rowId + '-form'); + } - static getRemoteData (table) - { - const data = { - limit: table.getAttribute('data-limit'), - offset: table.getAttribute('data-offset'), - sorting: table.getAttribute('data-sorting'), - filter: table.getAttribute('data-filter') - }; + // insert row values data into form + length = values.length; + for (let i = 0; i < length; ++i) { + document.getElementById(formId).querySelectorAll('[data-tpl-value="' + values[i].getAttribute('data-tpl-value') + '"')[0].value = values[i].value; + // todo: handle different input types + } - const request = new jsOMS.Message.Request.Request(); - request.setData(data); - request.setType(jsOMS.Message.Response.ResponseType.JSON); - request.setUri(table.getAttribute('data-src')); - request.setMethod('GET'); - request.setRequestHeader('Content-Type', 'application/json'); - request.setSuccess(function (xhr) { - jsOMS.UI.Component.Table.emptyTable(table.getElementsByTagName('tbody')[0]); - jsOMS.UI.Component.Table.addToTable(table.getElementsByTagName('tbody')[0], JSON.parse(xhr.response)); - }); + // insert row text data into form + length = text.length; + for (let i = 0; i < length; ++i) { + document.getElementById(formId).querySelectorAll('[data-tpl-text="' + text[i].getAttribute('data-tpl-text') + '"')[0].value = text[i].innerText; + console.log(text[i].innerText); + // todo: handle different input types + } - request.send(); - }; - - static emptyTable(table) - { - const rows = table.getElementsByTagName('tr'); - const length = rows.length; - - for (let i = 0; i < length; ++i) { - rows[i].parentNode.removeChild(rows[i]); + // todo: replace add button with save button and add cancel button + // todo: on save button click insert data into hidden row and show hidden row again, delete form row + // todo: consider to highlight column during edit } - }; - - static addToTable(table, data) - { - const dataLength = data.length; - - console.table(data); - - for (let i = 0; i < dataLength; ++i) { - // set readable value - const newRow = table.getElementsByTagName('template')[0].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]) - ); - } - - table.appendChild(newRow); - - // todo: bind buttons if required (e.g. remove, edit button) - } - }; - - bindUpdatable (update, id) - { - const self = this; - - update.addEventListener('click', function() { - // handle external form - // handle internal form - const formId = document.getElementById(id).getAttribute('data-table-form'); - const values = this.closest('tr').querySelectorAll('[data-tpl-value]'); - const text = this.closest('tr').querySelectorAll('[data-tpl-text]'); - const table = document.getElementById(id).getElementsByTagName('tbody')[0]; - - if (document.getElementById(formId) === null) { - this.closest('tr').style = "display: none"; // todo: replace with class instead of inline style - - const newRow = table.getElementsByTagName('template')[1].content.cloneNode(true); - const rowId = 'f' + Math.random().toString(36).substring(7); - // todo: don't use random ide use actual row id for data which needs to be updated - - newRow.firstElementChild.id = rowId; - newRow.firstElementChild.getElementsByTagName('form')[0].id = rowId + '-form'; - - const fields = newRow.firstElementChild.querySelectorAll('[data-form="' + self.tables[id].getForm() + '"]'); - let length = fields.length; - - for (let i = 0; i < length; ++i) { - fields[i].setAttribute('data-form', rowId + '-form'); - } - - // insert row values data into form - length = values.length; - for (let i = 0; i < length; ++i) { - newRow.firstElementChild.querySelectorAll('[data-tpl-value="' + values[i].getAttribute('data-tpl-value') + '"')[0].value = values[i].value; - // todo: handle different input types - } - - // insert row text data into form - length = text.length; - for (let i = 0; i < length; ++i) { - newRow.firstElementChild.querySelectorAll('[data-tpl-text="' + text[i].getAttribute('data-tpl-text') + '"')[0].value = text[i].innerText; - console.log(text[i].innerText); - // todo: handle different input types - } - - table.insertBefore(newRow.firstElementChild, this.closest('tr')); - - self.bindCreateForm(rowId + '-form', id); - self.app.uiManager.getFormManager().get(rowId + '-form').injectSubmit(function () { - document.getElementById(id).getElementsByTagName('tbody')[0].removeChild( - document.getElementById(rowId) - ); - }); - - // todo: replace add button with save button and add cancel button - // todo: on save button click insert data into hidden row and show hidden row again, delete form row - } else { - const fields = document.getElementById(formId).querySelectorAll('[data-form="' + self.tables[id].getForm() + '"]'); - let length = fields.length; - - for (let i = 0; i < length; ++i) { - fields[i].setAttribute('data-form', rowId + '-form'); - } - - // insert row values data into form - length = values.length; - for (let i = 0; i < length; ++i) { - document.getElementById(formId).querySelectorAll('[data-tpl-value="' + values[i].getAttribute('data-tpl-value') + '"')[0].value = values[i].value; - // todo: handle different input types - } - - // insert row text data into form - length = text.length; - for (let i = 0; i < length; ++i) { - document.getElementById(formId).querySelectorAll('[data-tpl-text="' + text[i].getAttribute('data-tpl-text') + '"')[0].value = text[i].innerText; - console.log(text[i].innerText); - // todo: handle different input types - } - - // todo: replace add button with save button and add cancel button - // todo: on save button click insert data into hidden row and show hidden row again, delete form row - // todo: consider to highlight column during edit - } - }); - }; - } -}(window.jsOMS = window.jsOMS || {})); + }); + }; +}; diff --git a/UI/DragNDrop.js b/UI/DragNDrop.js index 8da66cc..0bdb47d 100644 --- a/UI/DragNDrop.js +++ b/UI/DragNDrop.js @@ -6,129 +6,121 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class DragNDrop { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor (app) + { + this.app = app; + this.draggable = {}; + this.dragging = null; + }; - /** @namespace jsOMS.UI.DragNDrop*/ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.DragNDrop'); + /** + * Unbind element + * + * @param {Object} element DOM element + * + * @return {void} + * + * @since 1.0.0 + */ + unbind (element) + { + }; - jsOMS.UI.DragNDrop = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor (app) - { - this.app = app; - this.draggable = {}; - this.dragging = null; - }; + /** + * Bind element + * + * @param {Object} id DOM element + * + * @return {void} + * + * @since 1.0.0 + */ + bind (id) + { + if (typeof id !== 'undefined') { + this.bindElement(id); + } else { + const elements = document.querySelectorAll('[draggable]'), + length = !elements ? 0 : elements.length; - /** - * Unbind element - * - * @param {Object} element DOM element - * - * @return {void} - * - * @since 1.0.0 - */ - unbind (element) - { - }; - - /** - * Bind element - * - * @param {Object} id DOM element - * - * @return {void} - * - * @since 1.0.0 - */ - bind (id) - { - if (typeof id !== 'undefined') { - this.bindElement(id); - } else { - const elements = document.querySelectorAll('[draggable]'), - length = !elements ? 0 : elements.length; - - for (let i = 0; i < length; ++i) { - if (typeof elements[i].getAttribute('id') !== 'undefined' && elements[i].getAttribute('id') !== null) { - this.bindElement(elements[i].getAttribute('id')); - } + for (let i = 0; i < length; ++i) { + if (typeof elements[i].getAttribute('id') !== 'undefined' && elements[i].getAttribute('id') !== null) { + this.bindElement(elements[i].getAttribute('id')); } } - }; + } + }; - /** - * Bind DOM elment - * - * @param {string} id DOM element - * - * @return {void} - * - * @since 1.0.0 - */ - bindElement (id) - { - const element = document.getElementById(id), - self = this; + /** + * Bind DOM elment + * + * @param {string} id DOM element + * + * @return {void} + * + * @since 1.0.0 + */ + bindElement (id) + { + const element = document.getElementById(id), + self = this; - if (!element) { + if (!element) { + return; + } + + element.addEventListener('dragstart', function(e) { + if (self.dragging === null) { + self.dragging = this; + e.dataTransfer.effectAllowed = 'move'; + e.dataTransfer.setData('text/html', this.innerHTML); + } + }, false); + + element.addEventListener('dragenter', function(e) { + // todo: highlight + }, false); + + element.addEventListener('dragover', function(e) { + e.preventDefault(); + + e.dataTransfer.dropEffect = 'move'; + }, false); + + element.addEventListener('dragleave', function(e) { + e.preventDefault(); + + // todo: don't highlight + }, false); + + element.addEventListener('dragend', function(e) { + e.preventDefault(); + + // todo: reset all changes + }, false); + + //element.addEventListener('drag', function(e) {}); + element.addEventListener('drop', function(e) { + e.stopPropagation(); + e.preventDefault(); + + if (self.dragging === this) { return; } - element.addEventListener('dragstart', function(e) { - if (self.dragging === null) { - self.dragging = this; - e.dataTransfer.effectAllowed = 'move'; - e.dataTransfer.setData('text/html', this.innerHTML); - } - }, false); + self.dragging.innerHTML = this.innerHTML; + this.innerHTML = e.dataTransfer.getData('text/html'); - element.addEventListener('dragenter', function(e) { - // todo: highlight - }, false); + // todo: add to now destination + // todo: remove from old destination - element.addEventListener('dragover', function(e) { - e.preventDefault(); - - e.dataTransfer.dropEffect = 'move'; - }, false); - - element.addEventListener('dragleave', function(e) { - e.preventDefault(); - - // todo: don't highlight - }, false); - - element.addEventListener('dragend', function(e) { - e.preventDefault(); - - // todo: reset all changes - }, false); - - //element.addEventListener('drag', function(e) {}); - element.addEventListener('drop', function(e) { - e.stopPropagation(); - e.preventDefault(); - - if (self.dragging === this) { - return; - } - - self.dragging.innerHTML = this.innerHTML; - this.innerHTML = e.dataTransfer.getData('text/html'); - - // todo: add to now destination - // todo: remove from old destination - - self.dragging = null; - }, false); - } + self.dragging = null; + }, false); } -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file +}; \ No newline at end of file diff --git a/UI/GeneralUI.js b/UI/GeneralUI.js index 68f3b2c..5a22a08 100644 --- a/UI/GeneralUI.js +++ b/UI/GeneralUI.js @@ -1,3 +1,7 @@ + +import { AdvancedInput } from './Component/AdvancedInput.js'; +import { UriFactory } from '../Uri/UriFactory.js'; + /** * UI manager for handling basic ui elements. * @@ -6,121 +10,113 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class GeneralUI { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + this.visObs = null; + }; - /** @namespace jsOMS.UI */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI'); + /** + * Bind button. + * + * @param {string} [id] Button id (optional) + * + * @return {void} + * + * @since 1.0.0 + */ + bind (id) + { + let e = null; + if (typeof id !== 'undefined' && id !== null) { + e = document.getElementById(id); + } - jsOMS.UI.GeneralUI = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () - { - this.visObs = null; - }; + this.bindHref(e); + this.bindLazyLoad(e); + this.bindInput(e); + }; - /** - * Bind button. - * - * @param {string} [id] Button id (optional) - * - * @return {void} - * - * @since 1.0.0 - */ - bind (id) - { - let e = null; - if (typeof id !== 'undefined' && id !== null) { - e = document.getElementById(id); - } + /** + * Bind & rebind UI element. + * + * @param {Object} [e] Element id + * + * @return {void} + * + * @since 1.0.0 + */ + bindHref (e) + { + e = e !== null ? e.querySelectorAll('[data-href]') : document.querySelectorAll('[data-href]'); + const length = e.length; - this.bindHref(e); - this.bindLazyLoad(e); - this.bindInput(e); - }; + for (let i = 0; i < length; ++i) { + e[i].addEventListener('click', function(event) { + jsOMS.preventAll(event); + window.location = UriFactory.build(this.getAttribute('data-href')); + }); + } + }; - /** - * Bind & rebind UI element. - * - * @param {Object} [e] Element id - * - * @return {void} - * - * @since 1.0.0 - */ - bindHref (e) - { - e = e !== null ? e.querySelectorAll('[data-href]') : document.querySelectorAll('[data-href]'); - const length = e.length; + /** + * Bind & rebind UI element. + * + * @param {Object} [e] Element id + * + * @return {void} + * + * @since 1.0.0 + */ + bindLazyLoad (e) + { + e = e !== null ? e.querySelectorAll('[data-lazyload]') : document.querySelectorAll('[data-lazyload]'); + const length = e.length; - for (let i = 0; i < length; ++i) { - e[i].addEventListener('click', function(event) { - jsOMS.preventAll(event); - window.location = jsOMS.Uri.UriFactory.build(this.getAttribute('data-href')); + /** global: IntersectionObserver */ + if (!this.visObs && window.IntersectionObserver) { + this.visObs = new IntersectionObserver(function(eles, obs) { + eles.forEach(ele => { + if (ele.intersectionRatio > 0) { + obs.unobserve(ele.target); + ele.target.src = ele.target.dataset.lazyload; + delete ele.target.dataset.lazyload; + } }); + }); + } + + for (let i = 0; i < length; ++i) { + if (!this.visObs) { + e[i].src = e[i].dataset.lazyload; + delete e[i].dataset.lazyload; + } else { + this.visObs.observe(e[i]); } - }; + } + }; - /** - * Bind & rebind UI element. - * - * @param {Object} [e] Element id - * - * @return {void} - * - * @since 1.0.0 - */ - bindLazyLoad (e) - { - e = e !== null ? e.querySelectorAll('[data-lazyload]') : document.querySelectorAll('[data-lazyload]'); - const length = e.length; + /** + * Bind & rebind UI element. + * + * @param {Object} [e] Element id + * + * @return {void} + * + * @since 1.0.0 + */ + bindInput (e) + { + e = e !== null ? [e] : document.getElementsByClassName('advancedInput'); + const length = e.length; - /** global: IntersectionObserver */ - if (!this.visObs && window.IntersectionObserver) { - this.visObs = new IntersectionObserver(function(eles, obs) { - eles.forEach(ele => { - if (ele.intersectionRatio > 0) { - obs.unobserve(ele.target); - ele.target.src = ele.target.dataset.lazyload; - delete ele.target.dataset.lazyload; - } - }); - }); - } - - for (let i = 0; i < length; ++i) { - if (!this.visObs) { - e[i].src = e[i].dataset.lazyload; - delete e[i].dataset.lazyload; - } else { - this.visObs.observe(e[i]); - } - } - }; - - /** - * Bind & rebind UI element. - * - * @param {Object} [e] Element id - * - * @return {void} - * - * @since 1.0.0 - */ - bindInput (e) - { - e = e !== null ? [e] : document.getElementsByClassName('advancedInput'); - const length = e.length; - - for (let i = 0; i < length; ++i) { - new jsOMS.UI.Component.AdvancedInput(e[i]); - } - }; - } -}(window.jsOMS = window.jsOMS || {})); + for (let i = 0; i < length; ++i) { + new AdvancedInput(e[i]); + } + }; +}; diff --git a/UI/Input/InputManager.js b/UI/Input/InputManager.js index 06dd1b6..fb1c878 100644 --- a/UI/Input/InputManager.js +++ b/UI/Input/InputManager.js @@ -1,3 +1,7 @@ +import { KeyboardManager } from '../../../jsOMS/UI/Input/Keyboard/KeyboardManager.js'; +import { MouseManager } from '../../../jsOMS/UI/Input/Mouse/MouseManager.js'; +import { VoiceManager } from '../../../jsOMS/UI/Input/Voice/VoiceManager.js'; + /** * UI manager class. * @@ -6,60 +10,52 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class InputManager { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor(app) + { + this.keyboardManager = new KeyboardManager(); + this.mouseManager = new MouseManager(); + this.voiceManager = new VoiceManager(app); + }; - /** @namespace jsOMS.UI.Input */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input'); + /** + * Get keyboard manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getKeyboardManager () + { + return this.keyboardManager; + }; - jsOMS.UI.Input.InputManager = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor(app) - { - this.keyboardManager = new jsOMS.UI.Input.Keyboard.KeyboardManager(); - this.mouseManager = new jsOMS.UI.Input.Mouse.MouseManager(); - this.voiceManager = new jsOMS.UI.Input.Voice.VoiceManager(app); - }; + /** + * Get mouse manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getMouseManager () + { + return this.mouseManager; + }; - /** - * Get keyboard manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getKeyboardManager () - { - return this.keyboardManager; - }; - - /** - * Get mouse manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getMouseManager () - { - return this.mouseManager; - }; - - /** - * Get voice manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getVoiceManager () - { - return this.voiceManager; - }; - } -}(window.jsOMS = window.jsOMS || {})); + /** + * Get voice manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getVoiceManager () + { + return this.voiceManager; + }; +}; diff --git a/UI/Input/Keyboard/KeyboardManager.js b/UI/Input/Keyboard/KeyboardManager.js index c20cd4d..772a377 100644 --- a/UI/Input/Keyboard/KeyboardManager.js +++ b/UI/Input/Keyboard/KeyboardManager.js @@ -6,116 +6,108 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class KeyboardManager { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + this.elements = {}; + this.down = []; + }; - /** @namespace jsOMS.UI.Input.Keyboard */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input.Keyboard'); + /** + * Add input listener. + * + * @param {string} element Container id + * @param {Array} keys Keyboard keys + * @param {callback} callback Callback + * + * @return {void} + * + * @since 1.0.0 + */ + add (element, keys, callback) + { + if (typeof this.elements[element] === 'undefined') { + this.elements[element] = []; - jsOMS.UI.Input.Keyboard.KeyboardManager = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () + this.bind(element); + } + + this.elements[element].push({keys: keys, callback: callback}); + }; + + /** + * Bind container for keyboard input. + * + * @param {string} element Container id + * + * @return {void} + * + * @since 1.0.0 + */ + bind (element) + { + const self = this; + + // todo: implement keyboard for selected elements right now only global hotkeys possible + document.addEventListener('keydown', function keyBind(event) { - this.elements = {}; - this.down = []; - }; + self.down.push(event.keyCode); + }); - /** - * Add input listener. - * - * @param {string} element Container id - * @param {Array} keys Keyboard keys - * @param {callback} callback Callback - * - * @return {void} - * - * @since 1.0.0 - */ - add (element, keys, callback) + document.addEventListener('keyup', function keyBind(event) { - if (typeof this.elements[element] === 'undefined') { - this.elements[element] = []; - - this.bind(element); + if (self.down.length > 0) { + self.run(element, event); + self.down = []; } + }); + }; - this.elements[element].push({keys: keys, callback: callback}); - }; + /** + * Execute callback based on key presses. + * + * @param {string} element Container id + * @param {Object} event Key event + * + * @return {void} + * + * @throws {Error} + * + * @since 1.0.0 + */ + run (element, event) + { + if (typeof this.elements[element] === 'undefined') { + throw 'Unexpected elmenet!'; + } - /** - * Bind container for keyboard input. - * - * @param {string} element Container id - * - * @return {void} - * - * @since 1.0.0 - */ - bind (element) - { - const self = this; + const actions = this.elements[element], + length = actions.length, + keyLength = this.down.length; + let match = false; - // todo: implement keyboard for selected elements right now only global hotkeys possible - document.addEventListener('keydown', function keyBind(event) - { - self.down.push(event.keyCode); - }); - - document.addEventListener('keyup', function keyBind(event) - { - if (self.down.length > 0) { - self.run(element, event); - self.down = []; - } - }); - }; - - /** - * Execute callback based on key presses. - * - * @param {string} element Container id - * @param {Object} event Key event - * - * @return {void} - * - * @throws {Error} - * - * @since 1.0.0 - */ - run (element, event) - { - if (typeof this.elements[element] === 'undefined') { - throw 'Unexpected elmenet!'; - } - - const actions = this.elements[element], - length = actions.length, - keyLength = this.down.length; - let match = false; - - for (let i = 0; i < length; ++i) { - for (let j = 0; j < keyLength; ++j) { - if (actions[i].keys.indexOf(this.down[j]) === -1) { - match = false; - - break; - } - - match = true; - } - - if (match) { - jsOMS.preventAll(event); - actions[i].callback(); + for (let i = 0; i < length; ++i) { + for (let j = 0; j < keyLength; ++j) { + if (actions[i].keys.indexOf(this.down[j]) === -1) { + match = false; break; } + + match = true; } - }; - } -}(window.jsOMS = window.jsOMS || {})); + + if (match) { + jsOMS.preventAll(event); + actions[i].callback(); + + break; + } + } + }; +}; diff --git a/UI/Input/Mouse/ClickType.js b/UI/Input/Mouse/ClickType.js index 679d086..4deb8b8 100644 --- a/UI/Input/Mouse/ClickType.js +++ b/UI/Input/Mouse/ClickType.js @@ -6,16 +6,8 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.UI.Input.Mouse */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input.Mouse'); - - jsOMS.UI.Input.Mouse.ClickType = Object.freeze({ - LEFT: 0, - MIDDLE: 1, - RIGHT: 2 - }); -}(window.jsOMS = window.jsOMS || {})); +export const ClickType = Object.freeze({ + LEFT: 0, + MIDDLE: 1, + RIGHT: 2 +}); diff --git a/UI/Input/Mouse/EventType.js b/UI/Input/Mouse/EventType.js index 837cbc2..7c63479 100644 --- a/UI/Input/Mouse/EventType.js +++ b/UI/Input/Mouse/EventType.js @@ -6,16 +6,8 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.UI.Input.Mouse */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input.Mouse'); - - jsOMS.UI.Input.Mouse.EventType = Object.freeze({ - CONTEXT: 0, - LONGPRESS: 1, - CLICK: 2 - }); -}(window.jsOMS = window.jsOMS || {})); +export const EventType = Object.freeze({ + CONTEXT: 0, + LONGPRESS: 1, + CLICK: 2 +}); diff --git a/UI/Input/Mouse/MouseManager.js b/UI/Input/Mouse/MouseManager.js index 0e9b7d4..2e10c4a 100644 --- a/UI/Input/Mouse/MouseManager.js +++ b/UI/Input/Mouse/MouseManager.js @@ -1,3 +1,5 @@ +import { EventType } from '../../../../jsOMS/UI/Input/Mouse/EventType.js'; + /** * Mouse manager class. * @@ -6,123 +8,115 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class MouseManager { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor () + { + this.elements = {}; + this.click = {time: 0}; + }; - /** @namespace jsOMS.UI.Input.Mouse */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input.Mouse'); + /** + * Add input listener. + * + * @param {string} element Container id + * @param {int} type Action type + * @param {int} button Button + * @param {callback} callback Callback + * @param {bool} exact ??? todo: can't remember why this was important oO!!! + * + * @return {void} + * + * @since 1.0.0 + */ + add (element, type, button, callback, exact) + { + if (typeof this.elements[element] === 'undefined') { + this.elements[element] = []; + } - jsOMS.UI.Input.Mouse.MouseManager = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor () - { - this.elements = {}; - this.click = {time: 0}; - }; + this.bind(element, type); + this.elements[element].push({callback: callback, type: type, button: button, exact: exact}); + }; - /** - * Add input listener. - * - * @param {string} element Container id - * @param {int} type Action type - * @param {int} button Button - * @param {callback} callback Callback - * @param {bool} exact ??? todo: can't remember why this was important oO!!! - * - * @return {void} - * - * @since 1.0.0 - */ - add (element, type, button, callback, exact) - { - if (typeof this.elements[element] === 'undefined') { - this.elements[element] = []; - } + /** + * Add input listener. + * + * @param {string} element Element id + * @param {int} type Action type + * + * @return {void} + * + * @since 1.0.0 + */ + bind (element, type) + { + const self = this, + e = document.getElementById(element); - this.bind(element, type); - this.elements[element].push({callback: callback, type: type, button: button, exact: exact}); - }; + if (!e) { + return; + } - /** - * Add input listener. - * - * @param {string} element Element id - * @param {int} type Action type - * - * @return {void} - * - * @since 1.0.0 - */ - bind (element, type) - { - const self = this, - e = document.getElementById(element); + if (type === EventType.CONTEXT) { + e.addEventListener('contextmenu', function (event) + { + self.run(element, event); + }, false); + } else if (type === EventType.LONGPRESS) { + e.addEventListener('mousedown', function (event) + { + self.click.time = new Date().getTime(); + }, false); - if (!e) { - return; - } + e.addEventListener('mouseup', function (event) + { + const duration = new Date().getTime() - self.click.time; - if (type === jsOMS.UI.Input.Mouse.EventType.CONTEXT) { - e.addEventListener('contextmenu', function (event) - { + if (duration > 650) { self.run(element, event); - }, false); - } else if (type === jsOMS.UI.Input.Mouse.EventType.LONGPRESS) { - e.addEventListener('mousedown', function (event) - { - self.click.time = new Date().getTime(); - }, false); - - e.addEventListener('mouseup', function (event) - { - const duration = new Date().getTime() - self.click.time; - - if (duration > 650) { - self.run(element, event); - } - - self.click.time = 0; - }, false); - } else if (type === jsOMS.UI.Input.Mouse.EventType.CLICK) { - e.addEventListener('click', function (event) - { - self.run(element, event); - }, false); - } - }; - - /** - * Run mouse input callback. - * - * @param {string} element Element id - * @param {Object} event Click event - * - * @return {void} - * - * @since 1.0.0 - */ - run (element, event) - { - if (typeof this.elements[element] === 'undefined') { - throw 'Unexpected elmenet!'; - } - - const actions = this.elements[element], - length = actions.length; - - for (let i = 0; i < length; ++i) { - if ((!actions[i].exact || event.target.getAttribute('id') === element) - && actions[i].button === event.button - ) { - jsOMS.preventAll(event); - actions[i].callback(); } + + self.click.time = 0; + }, false); + } else if (type === EventType.CLICK) { + e.addEventListener('click', function (event) + { + self.run(element, event); + }, false); + } + }; + + /** + * Run mouse input callback. + * + * @param {string} element Element id + * @param {Object} event Click event + * + * @return {void} + * + * @since 1.0.0 + */ + run (element, event) + { + if (typeof this.elements[element] === 'undefined') { + throw 'Unexpected elmenet!'; + } + + const actions = this.elements[element], + length = actions.length; + + for (let i = 0; i < length; ++i) { + if ((!actions[i].exact || event.target.getAttribute('id') === element) + && actions[i].button === event.button + ) { + jsOMS.preventAll(event); + actions[i].callback(); } - }; - } -}(window.jsOMS = window.jsOMS || {})); + } + }; +}; diff --git a/UI/Input/Touch/TouchManager.js b/UI/Input/Touch/TouchManager.js index 2d47f47..88cdebc 100644 --- a/UI/Input/Touch/TouchManager.js +++ b/UI/Input/Touch/TouchManager.js @@ -6,126 +6,118 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class TouchManager { + /** + * @constructor + * + * @param {Object} app Application + * + * @since 1.0.0 + */ + constructor (app) + { + this.app = app; + this.activeSwipe = {}; + this.resetSwipe(); + }; - /** @namespace jsOMS.UI.Input.Touch */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input.Touch'); + /** + * Reset swipe data. + * + * This is called in between swipes in order to reset previous swipe data. + * + * @return {void} + * + * @since 1.0.0 + */ + resetSwipe () + { + this.activeSwipe = {'startX': null, 'startY': null, 'time': null}; + }; - jsOMS.UI.Input.Touch.TouchManager = class { - /** - * @constructor - * - * @param {Object} app Application - * - * @since 1.0.0 - */ - constructor (app) + /** + * Adding swipe functionality. + * + * Forwarding swipe to arrow keys. + * + * @return {void} + * + * @since 1.0.0 + */ + add (surface) + { + const e = document.getElementById(surface), + self = this; + + if (!e) { + return; + } + + e.addEventListener('touchstart', function (event) { - this.app = app; - this.activeSwipe = {}; - this.resetSwipe(); - }; + const touch = this.changedTouches[0]; - /** - * Reset swipe data. - * - * This is called in between swipes in order to reset previous swipe data. - * - * @return {void} - * - * @since 1.0.0 - */ - resetSwipe () + self.activeSwipe.startX = touch.pageX; + self.activeSwipe.startY = touch.pageY; + self.activeSwipe.time = new Date().getTime(); + + jsOMS.preventAll(event); + }); + + e.addEventListener('touchmove', function (event) { - this.activeSwipe = {'startX': null, 'startY': null, 'time': null}; - }; + jsOMS.preventAll(event); + }); - /** - * Adding swipe functionality. - * - * Forwarding swipe to arrow keys. - * - * @return {void} - * - * @since 1.0.0 - */ - add (surface) + e.addEventListener('touchend', function (event) { - const e = document.getElementById(surface), - self = this; + const touch = this.changedTouches[0], + distX = touch.pageX - self.activeSwipe.startX, + distY = touch.pageY - self.activeSwipe.startY, + elapsedTime = new Date().getTime() - self.activeSwipe.time; - if (!e) { - return; - } + self.resetSwipe(); + // todo: only prevent all if success + jsOMS.preventAll(event); - e.addEventListener('touchstart', function (event) - { - const touch = this.changedTouches[0]; - - self.activeSwipe.startX = touch.pageX; - self.activeSwipe.startY = touch.pageY; - self.activeSwipe.time = new Date().getTime(); - - jsOMS.preventAll(event); - }); - - e.addEventListener('touchmove', function (event) - { - jsOMS.preventAll(event); - }); - - e.addEventListener('touchend', function (event) - { - const touch = this.changedTouches[0], - distX = touch.pageX - self.activeSwipe.startX, - distY = touch.pageY - self.activeSwipe.startY, - elapsedTime = new Date().getTime() - self.activeSwipe.time; - - self.resetSwipe(); - // todo: only prevent all if success - jsOMS.preventAll(event); - - if (elapsedTime > 300 && distY < 3 && distX < 3) { - let rightClick = MouseEvent('click', - { - bubbles: true, - cancelable: true, - view: window, - screenX: touch.pageX, - screenY: touch.pageY, - clientX: touch.pageX, - clientY: touch.pageY, - ctrlKey: false, - altKey: false, - shiftKey: false, - metaKey: false, - button: 2, - relatedTarget: null - } - ); - - document.dispatchEvent(rightClick); - } else if (elapsedTime < 500) { - /** global: Event */ - const e = new Event('keyup'); - - if (distY > 100) { - e.keyCode = 38; - document.dispatchEvent(e); - } else if (distX > 100) { - e.keyCode = 39; - document.dispatchEvent(e); - } else if (distY < -100) { - e.keyCode = 40; - document.dispatchEvent(e); - } else if (distX < -100) { - e.keyCode = 37; - document.dispatchEvent(e); + if (elapsedTime > 300 && distY < 3 && distX < 3) { + let rightClick = MouseEvent('click', + { + bubbles: true, + cancelable: true, + view: window, + screenX: touch.pageX, + screenY: touch.pageY, + clientX: touch.pageX, + clientY: touch.pageY, + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false, + button: 2, + relatedTarget: null } + ); + + document.dispatchEvent(rightClick); + } else if (elapsedTime < 500) { + /** global: Event */ + const e = new Event('keyup'); + + if (distY > 100) { + e.keyCode = 38; + document.dispatchEvent(e); + } else if (distX > 100) { + e.keyCode = 39; + document.dispatchEvent(e); + } else if (distY < -100) { + e.keyCode = 40; + document.dispatchEvent(e); + } else if (distX < -100) { + e.keyCode = 37; + document.dispatchEvent(e); } - }); - }; - } -}(window.jsOMS = window.jsOMS || {})); + } + }); + }; +}; diff --git a/UI/Input/Voice/ReadManager.js b/UI/Input/Voice/ReadManager.js index 1ce5f7f..40cffe2 100644 --- a/UI/Input/Voice/ReadManager.js +++ b/UI/Input/Voice/ReadManager.js @@ -6,121 +6,113 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class ReadManager { + /** + * @constructor + * + * @param {string} lang Localization + * + * @since 1.0.0 + */ + constructor (lang = 'en-US') + { + this.pitch = 1; + this.rate = 1; + this.lang = lang; + this.voices = []; + this.voice = null; - /** @namespace jsOMS.UI */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input.Voice'); + if (SpeechRecognition !== null) { + this.voices = window.speechSynthesis.getVoices(); + this.voice = this.voices[0]; + } + }; - // todo: remove once obsolete - /** global: webkitSpeechRecognition */ - /** global: SpeechRecognition */ - var SpeechRecognition = typeof SpeechRecognition !== 'undefined' ? SpeechRecognition : typeof webkitSpeechRecognition !== 'undefined' ? webkitSpeechRecognition : null; + /** + * Read text. + * + * @param {string} text Text to read + * + * @return {void} + * + * @since 1.0.0 + */ + read (text) + { + /** global: SpeechSynthesisUtterance */ + let utter = new SpeechSynthesisUtterance(text); + utter.lang = this.lang; + utter.voice = this.voice; + utter.pitch = this.pitch; + utter.rate = this.rate; - /** global: webkitSpeechGrammarList */ - /** global: SpeechGrammarList */ - var SpeechGrammarList = typeof SpeechGrammarList !== 'undefined' ? SpeechGrammarList : typeof webkitSpeechGrammarList !== 'undefined' ? webkitSpeechGrammarList : null; + window.speechSynthesis.speak(utter); + }; - /** global: webkitSpeechRecognitionEvent */ - /** global: SpeechRecognitionEvent */ - var SpeechRecognitionEvent = typeof SpeechRecognitionEvent !== 'undefined' ? SpeechRecognitionEvent : typeof webkitSpeechRecognitionEvent !== 'undefined' ? webkitSpeechRecognitionEvent : null; + /** + * Set Language. + * + * @param {string} lang Language id (e.g. en-US) + * + * @return {void} + * + * @since 1.0.0 + */ + setLanguage (lang) + { + this.lang = lang; + }; - jsOMS.UI.Input.Voice.ReadManager = class { - /** - * @constructor - * - * @param {string} lang Localization - * - * @since 1.0.0 - */ - constructor (lang = 'en-US') - { - this.pitch = 1; - this.rate = 1; - this.lang = lang; - this.voices = []; - this.voice = null; + /** + * Set pitch. + * + * @param {int} pitch Pitch + * + * @return {void} + * + * @since 1.0.0 + */ + setPitch (pitch) + { + this.pitch = pitch; + }; - if (SpeechRecognition !== null) { - this.voices = window.speechSynthesis.getVoices(); - this.voice = this.voices[0]; - } - }; + /** + * Set rate. + * + * @param {int} rate Rate + * + * @return {void} + * + * @since 1.0.0 + */ + setRate (rate) + { + this.rate = rate; + }; - /** - * Read text. - * - * @param {string} text Text to read - * - * @return {void} - * - * @since 1.0.0 - */ - read (text) - { - /** global: SpeechSynthesisUtterance */ - let utter = new SpeechSynthesisUtterance(text); - utter.lang = this.lang; - utter.voice = this.voice; - utter.pitch = this.pitch; - utter.rate = this.rate; + /** + * Get supported voices. + * + * @return {Array} + * + * @since 1.0.0 + */ + getVoices () + { + return this.voices; + }; +}; - window.speechSynthesis.speak(utter); - }; +// todo: remove once obsolete +/** global: webkitSpeechRecognition */ +/** global: SpeechRecognition */ +var SpeechRecognition = typeof SpeechRecognition !== 'undefined' ? SpeechRecognition : typeof webkitSpeechRecognition !== 'undefined' ? webkitSpeechRecognition : null; - /** - * Set Language. - * - * @param {string} lang Language id (e.g. en-US) - * - * @return {void} - * - * @since 1.0.0 - */ - setLanguage (lang) - { - this.lang = lang; - }; +/** global: webkitSpeechGrammarList */ +/** global: SpeechGrammarList */ +var SpeechGrammarList = typeof SpeechGrammarList !== 'undefined' ? SpeechGrammarList : typeof webkitSpeechGrammarList !== 'undefined' ? webkitSpeechGrammarList : null; - /** - * Set pitch. - * - * @param {int} pitch Pitch - * - * @return {void} - * - * @since 1.0.0 - */ - setPitch (pitch) - { - this.pitch = pitch; - }; - - /** - * Set rate. - * - * @param {int} rate Rate - * - * @return {void} - * - * @since 1.0.0 - */ - setRate (rate) - { - this.rate = rate; - }; - - /** - * Get supported voices. - * - * @return {Array} - * - * @since 1.0.0 - */ - getVoices () - { - return this.voices; - }; - } -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file +/** global: webkitSpeechRecognitionEvent */ +/** global: SpeechRecognitionEvent */ +var SpeechRecognitionEvent = typeof SpeechRecognitionEvent !== 'undefined' ? SpeechRecognitionEvent : typeof webkitSpeechRecognitionEvent !== 'undefined' ? webkitSpeechRecognitionEvent : null; \ No newline at end of file diff --git a/UI/Input/Voice/VoiceManager.js b/UI/Input/Voice/VoiceManager.js index 82f6525..1581de7 100644 --- a/UI/Input/Voice/VoiceManager.js +++ b/UI/Input/Voice/VoiceManager.js @@ -6,172 +6,164 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class VoiceManager { + /** + * @constructor + * + * @param {Object} app Application + * @param {Object} commands Available commands + * @param {string} lang Localization + * + * @since 1.0.0 + */ + constructor(app, commands = {}, lang = 'en-US') + { + this.app = app; + this.commands = commands; + this.lang = lang; + this.recognition = null; + this.speechRecognitionList = null; - /** @namespace jsOMS.UI */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input.Voice'); + if (SpeechRecognition !== null) { + this.recognition = new SpeechRecognition(); + this.speechRecognitionList = new SpeechGrammarList(); + } + }; - // todo: remove once obsolete - /** global: webkitSpeechRecognition */ - /** global: SpeechRecognition */ - var SpeechRecognition = typeof SpeechRecognition !== 'undefined' ? SpeechRecognition : typeof webkitSpeechRecognition !== 'undefined' ? webkitSpeechRecognition : null; + /** + * Setup or re-initialize voice manager. + * + * @return {void} + * + * @since 1.0.0 + */ + setup() + { + if (SpeechRecognition === null) { + return; + } - /** global: webkitSpeechGrammarList */ - /** global: SpeechGrammarList */ - var SpeechGrammarList = typeof SpeechGrammarList !== 'undefined' ? SpeechGrammarList : typeof webkitSpeechGrammarList !== 'undefined' ? webkitSpeechGrammarList : null; + const self = this; + this.recognition.lang = this.lang; + this.recognition.interimResults = false; + this.recognition.maxAlternatives = 1; + this.recognition.continuous = true; + this.recognition.lang = this.lang; - /** global: webkitSpeechRecognitionEvent */ - /** global: SpeechRecognitionEvent */ - var SpeechRecognitionEvent = typeof SpeechRecognitionEvent !== 'undefined' ? SpeechRecognitionEvent : typeof webkitSpeechRecognitionEvent !== 'undefined' ? webkitSpeechRecognitionEvent : null; + if (typeof this.commands !== 'undefined') { + this.speechRecognitionList.addFromString(this.getCommandsString(), 1); + this.recognition.grammars = this.speechRecognitionList; + } - jsOMS.UI.Input.Voice.VoiceManager = class { - /** - * @constructor - * - * @param {Object} app Application - * @param {Object} commands Available commands - * @param {string} lang Localization - * - * @since 1.0.0 - */ - constructor(app, commands = {}, lang = 'en-US') + this.recognition.onstart = function() {}; + this.recognition.onresult = function(event) { - this.app = app; - this.commands = commands; - this.lang = lang; - this.recognition = null; - this.speechRecognitionList = null; + let result = jsOMS.trim(event.results[event.resultIndex][0].transcript); - if (SpeechRecognition !== null) { - this.recognition = new SpeechRecognition(); - this.speechRecognitionList = new SpeechGrammarList(); + if (self.commands.hasOwnProperty(result)) { + self.commands[result](); } }; - /** - * Setup or re-initialize voice manager. - * - * @return {void} - * - * @since 1.0.0 - */ - setup() + this.recognition.onspeechend = function() { - if (SpeechRecognition === null) { - return; - } - - const self = this; - this.recognition.lang = this.lang; - this.recognition.interimResults = false; - this.recognition.maxAlternatives = 1; - this.recognition.continuous = true; - this.recognition.lang = this.lang; - - if (typeof this.commands !== 'undefined') { - this.speechRecognitionList.addFromString(this.getCommandsString(), 1); - this.recognition.grammars = this.speechRecognitionList; - } - - this.recognition.onstart = function() {}; - this.recognition.onresult = function(event) - { - let result = jsOMS.trim(event.results[event.resultIndex][0].transcript); - - if (self.commands.hasOwnProperty(result)) { - self.commands[result](); - } - }; - - this.recognition.onspeechend = function() - { - }; - - this.recognition.onnomatch = function(event) - { - jsOMS.Log.Logger.instance.warning('Couldn\'t recognize speech'); - }; - - this.recognition.onerror = function(event) - { - jsOMS.Log.Logger.instance.warning('Error during speech recognition: ' + event.error); - }; }; - /** - * Create commands/grammar string from commands - * - * @return {string} - * - * @since 1.0.0 - */ - getCommandsString() + this.recognition.onnomatch = function(event) { - return '#JSGF V1.0; grammar phrase; public = ' + Object.keys(this.commands).join(' | ') + ' ;'; + jsOMS.Log.Logger.instance.warning('Couldn\'t recognize speech'); }; - /** - * Set language - * - * @param {string} lang Language code (e.g. en-US) - * - * @return {void} - * - * @since 1.0.0 - */ - setLanguage(lang) + this.recognition.onerror = function(event) { - // todo: eventually restart - this.recognition.lang = lang; + jsOMS.Log.Logger.instance.warning('Error during speech recognition: ' + event.error); }; + }; - /** - * Add command/grammar and callback. - * - * @param {string} command Command id - * @param {callback} callback Callback for command - * - * @return {void} - * - * @since 1.0.0 - */ - add(command, callback) - { - this.commands[command] = callback; - }; + /** + * Create commands/grammar string from commands + * + * @return {string} + * + * @since 1.0.0 + */ + getCommandsString() + { + return '#JSGF V1.0; grammar phrase; public = ' + Object.keys(this.commands).join(' | ') + ' ;'; + }; - /** - * Start voice listener. - * - * @return {void} - * - * @since 1.0.0 - */ - start() - { - if (SpeechRecognition === null) { - return; - } + /** + * Set language + * + * @param {string} lang Language code (e.g. en-US) + * + * @return {void} + * + * @since 1.0.0 + */ + setLanguage(lang) + { + // todo: eventually restart + this.recognition.lang = lang; + }; - this.recognition.start(); - }; + /** + * Add command/grammar and callback. + * + * @param {string} command Command id + * @param {callback} callback Callback for command + * + * @return {void} + * + * @since 1.0.0 + */ + add(command, callback) + { + this.commands[command] = callback; + }; - /** - * Stop voice listener. - * - * @return {void} - * - * @since 1.0.0 - */ - stop() - { - if (SpeechRecognition === null) { - return; - } + /** + * Start voice listener. + * + * @return {void} + * + * @since 1.0.0 + */ + start() + { + if (SpeechRecognition === null) { + return; + } - this.recognition.stop(); - }; - } -}(window.jsOMS = window.jsOMS || {})); \ No newline at end of file + this.recognition.start(); + }; + + /** + * Stop voice listener. + * + * @return {void} + * + * @since 1.0.0 + */ + stop() + { + if (SpeechRecognition === null) { + return; + } + + this.recognition.stop(); + }; +}; + +// todo: remove once obsolete +/** global: webkitSpeechRecognition */ +/** global: SpeechRecognition */ +var SpeechRecognition = typeof SpeechRecognition !== 'undefined' ? SpeechRecognition : typeof webkitSpeechRecognition !== 'undefined' ? webkitSpeechRecognition : null; + +/** global: webkitSpeechGrammarList */ +/** global: SpeechGrammarList */ +var SpeechGrammarList = typeof SpeechGrammarList !== 'undefined' ? SpeechGrammarList : typeof webkitSpeechGrammarList !== 'undefined' ? webkitSpeechGrammarList : null; + +/** global: webkitSpeechRecognitionEvent */ +/** global: SpeechRecognitionEvent */ +var SpeechRecognitionEvent = typeof SpeechRecognitionEvent !== 'undefined' ? SpeechRecognitionEvent : typeof webkitSpeechRecognitionEvent !== 'undefined' ? webkitSpeechRecognitionEvent : null; \ No newline at end of file diff --git a/UI/UIManager.js b/UI/UIManager.js index 496d0e4..3348cf0 100644 --- a/UI/UIManager.js +++ b/UI/UIManager.js @@ -1,3 +1,10 @@ +import { Form } from '../UI/Component/Form.js'; +import { Tab } from '../UI/Component/Tab.js'; +import { Table } from '../UI/Component/Table.js'; +import { ActionManager } from '../UI/ActionManager.js'; +import { DragNDrop } from '../UI/DragNDrop.js'; +import { GeneralUI } from '../UI/GeneralUI.js'; + /** * UI manager for handling basic ui elements. * @@ -6,163 +13,155 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class UIManager { + /** + * @constructor + * + * @param {Object} app Application object + * + * @since 1.0.0 + */ + constructor(app) + { + this.app = app; + this.formManager = new Form(this.app); + this.tabManager = new Tab(this.app); + this.tableManager = new Table(this.app); + this.actionManager = new ActionManager(this.app); + this.dragNDrop = new DragNDrop(this.app); + this.generalUI = new GeneralUI(); - /** @namespace jsOMS.UI */ - jsOMS.Autoloader.defineNamespace('jsOMS.UI'); + const self = this; + /** global: MutationObserver */ + this.domObserver = new MutationObserver(function(mutations) { + const length = mutations.length; - jsOMS.UI.UIManager = class { - /** - * @constructor - * - * @param {Object} app Application object - * - * @since 1.0.0 - */ - constructor(app) - { - this.app = app; - this.formManager = new jsOMS.UI.Component.Form(this.app); - this.tabManager = new jsOMS.UI.Component.Tab(this.app); - this.tableManager = new jsOMS.UI.Component.Table(this.app); - this.actionManager = new jsOMS.UI.ActionManager(this.app); - this.dragNDrop = new jsOMS.UI.DragNDrop(this.app); - this.generalUI = new jsOMS.UI.GeneralUI(); - - const self = this; - /** global: MutationObserver */ - this.domObserver = new MutationObserver(function(mutations) { - const length = mutations.length; - - for(let i = 0; i < length; ++i) { - self.app.eventManager.trigger(mutations[i].target.id + '-' + mutations[i].type, 0, mutations[i]); - } - }); - }; - - /** - * Bind & rebind UI elements. - * - * @param {string} [id] Element id - * - * @return {void} - * - * @since 1.0.0 - */ - bind(id) - { - if (typeof id === 'undefined') { - this.formManager.bind(); - this.tabManager.bind(); - this.tableManager.bind(); - this.actionManager.bind(); - this.dragNDrop.bind(); - this.generalUI.bind(); - } else { - const tag = document.getElementById(id); - this.generalUI.bind(tag); - - if(!tag) { - return; - } - - switch (tag.tagName) { - case 'form': - this.formManager.bind(id); - break; - case 'table': - this.tableManager.bind(id); - break; - default: - this.actionManager.bind(tag); - } + for(let i = 0; i < length; ++i) { + self.app.eventManager.trigger(mutations[i].target.id + '-' + mutations[i].type, 0, mutations[i]); } - }; + }); + }; - /** - * Get tab manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getFormManager() - { - return this.formManager; - }; + /** + * Bind & rebind UI elements. + * + * @param {string} [id] Element id + * + * @return {void} + * + * @since 1.0.0 + */ + bind(id) + { + if (typeof id === 'undefined') { + this.formManager.bind(); + this.tabManager.bind(); + this.tableManager.bind(); + this.actionManager.bind(); + this.dragNDrop.bind(); + this.generalUI.bind(); + } else { + const tag = document.getElementById(id); + this.generalUI.bind(tag); - /** - * Get action manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getActionManager() - { - return this.actionManager; - }; + if(!tag) { + return; + } - /** - * Get drag and drop manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getDragNDrop() - { - return this.dragNDrop; - }; + switch (tag.tagName) { + case 'form': + this.formManager.bind(id); + break; + case 'table': + this.tableManager.bind(id); + break; + default: + this.actionManager.bind(tag); + } + } + }; - /** - * Get tab manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getTabManager() - { - return this.tabManager; - }; + /** + * Get tab manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getFormManager() + { + return this.formManager; + }; - /** - * Get table manager. - * - * @return {Object} - * - * @since 1.0.0 - */ - getTableManager() - { - return this.tabManager; - }; + /** + * Get action manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getActionManager() + { + return this.actionManager; + }; - /** - * Get DOM observer - * - * @return {Object} - * - * @since 1.0.0 - */ - getDOMObserver() - { - return this.domObserver; - }; + /** + * Get drag and drop manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getDragNDrop() + { + return this.dragNDrop; + }; - /** - * Get general UI - * - * @return {Object} - * - * @since 1.0.0 - */ - getGeneralUI() - { - return this.generalUI; - }; - } -}(window.jsOMS = window.jsOMS || {})); + /** + * Get tab manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getTabManager() + { + return this.tabManager; + }; + + /** + * Get table manager. + * + * @return {Object} + * + * @since 1.0.0 + */ + getTableManager() + { + return this.tabManager; + }; + + /** + * Get DOM observer + * + * @return {Object} + * + * @since 1.0.0 + */ + getDOMObserver() + { + return this.domObserver; + }; + + /** + * Get general UI + * + * @return {Object} + * + * @since 1.0.0 + */ + getGeneralUI() + { + return this.generalUI; + }; +}; \ No newline at end of file diff --git a/UnhandledException.js b/UnhandledException.js index a7989f2..b409d87 100644 --- a/UnhandledException.js +++ b/UnhandledException.js @@ -14,7 +14,7 @@ window.addEventListener('error', function (e) { /** global: jsOMS */ - jsOMS.Log.Logger.instance.error(e.error); + //jsOMS.Log.Logger.instance.error(e.error); return false; }); diff --git a/Uri/Http.js b/Uri/Http.js index 5fbddc9..9f000db 100644 --- a/Uri/Http.js +++ b/Uri/Http.js @@ -8,319 +8,311 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; +export class Http { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor(uri) + { + this.uri = ''; + this.scheme = ''; + this.host = ''; + this.port = ''; + this.user = ''; + this.pass = ''; + this.query = null; + this.queryString = ''; + this.fragment = ''; + this.base = ''; + this.root = '/'; - /** @namespace jsOMS.Uri.UriFactory */ - jsOMS.Autoloader.defineNamespace('jsOMS.Uri.Http'); + this.set(uri); + }; - jsOMS.Uri.Http = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor(uri) - { - this.uri = ''; - this.scheme = ''; - this.host = ''; - this.port = ''; - this.user = ''; - this.pass = ''; - this.query = null; - this.queryString = ''; - this.fragment = ''; - this.base = ''; - this.root = '/'; + /** + * Parse uri + * + * @param {string} str Url to parse + * @param {string} [mode] Parsing mode + * + * @return {Object} + * + * @throws {Error} + * + * @since 1.0.0 + */ + static parseUrl (str, mode = 'php') + { + const key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', + 'relative', 'path', 'directory', 'file', 'query', 'fragment' + ], + parser = { + php: /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-scheme to catch file:/// (should restrict this) + }; - this.set(uri); - }; + if (!parser.hasOwnProperty(mode)) { + throw new Error('Unexpected parsing mode.', 'UriFactory', 52); + } - /** - * Parse uri - * - * @param {string} str Url to parse - * @param {string} [mode] Parsing mode - * - * @return {Object} - * - * @throws {Error} - * - * @since 1.0.0 - */ - static parseUrl (str, mode = 'php') - { - const key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', - 'relative', 'path', 'directory', 'file', 'query', 'fragment' - ], - parser = { - php: /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-scheme to catch file:/// (should restrict this) - }; + const m = parser[mode].exec(str), + uri = {}; + let i = 14; - if (!parser.hasOwnProperty(mode)) { - throw new Error('Unexpected parsing mode.', 'UriFactory', 52); + while (--i) { + if (m[i]) { + uri[key[i]] = m[i]; } + } - const m = parser[mode].exec(str), - uri = {}; - let i = 14; + delete uri.source; - while (--i) { - if (m[i]) { - uri[key[i]] = m[i]; + return uri; + }; + + /** + * Get Uri query parameters. + * + * @param {string} query Uri query + * @param {string} name Name of the query to return + * + * @return {null|string} + * + * @since 1.0.0 + */ + static getUriQueryParameter (query, name) + { + name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); + + const regex = new RegExp("[\\?&]*" + name + "=([^&#]*)"), + results = regex.exec(query); + + return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); + }; + + /** + * Get all uri query parameters. + * + * @param {string} query Uri query + * + * @return {Object} + * + * @since 1.0.0 + */ + static getAllUriQueryParameters (query) + { + const params = {}; + let keyValPairs = [], + pairNum = null; + + if (query.length) { + keyValPairs = query.split('&'); + + for (pairNum in keyValPairs) { + if (!keyValPairs.hasOwnProperty(pairNum)) { + continue; } - } - delete uri.source; + const key = keyValPairs[pairNum].split('=')[0]; - return uri; - }; - - /** - * Get Uri query parameters. - * - * @param {string} query Uri query - * @param {string} name Name of the query to return - * - * @return {null|string} - * - * @since 1.0.0 - */ - static getUriQueryParameter (query, name) - { - name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); - - const regex = new RegExp("[\\?&]*" + name + "=([^&#]*)"), - results = regex.exec(query); - - return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); - }; - - /** - * Get all uri query parameters. - * - * @param {string} query Uri query - * - * @return {Object} - * - * @since 1.0.0 - */ - static getAllUriQueryParameters (query) - { - const params = {}; - let keyValPairs = [], - pairNum = null; - - if (query.length) { - keyValPairs = query.split('&'); - - for (pairNum in keyValPairs) { - if (!keyValPairs.hasOwnProperty(pairNum)) { - continue; - } - - const key = keyValPairs[pairNum].split('=')[0]; - - if (!key.length) { - continue; - } - - if (typeof params[key] === 'undefined') { - params[key] = []; - } - - params[key].push(keyValPairs[pairNum].split('=')[1]); + if (!key.length) { + continue; } + + if (typeof params[key] === 'undefined') { + params[key] = []; + } + + params[key].push(keyValPairs[pairNum].split('=')[1]); } + } - return params; - }; + return params; + }; - /** - * Set uri. - * - * @param {string} uri Uri string - * - * @return {void} - * - * @since 1.0.0 - */ - set (uri) - { - this.uri = uri; + /** + * Set uri. + * + * @param {string} uri Uri string + * + * @return {void} + * + * @since 1.0.0 + */ + set (uri) + { + this.uri = uri; - const parsed = jsOMS.Uri.Http.parseUrl(this.uri, 'php'); + const parsed = Http.parseUrl(this.uri, 'php'); - this.scheme = parsed['scheme']; - this.host = parsed['host']; - this.port = parsed['port']; - this.user = parsed['user']; - this.pass = parsed['pass']; - this.path = parsed['path']; + this.scheme = parsed['scheme']; + this.host = parsed['host']; + this.port = parsed['port']; + this.user = parsed['user']; + this.pass = parsed['pass']; + this.path = parsed['path']; - if (this.path.endsWith('.php')) { - this.path = this.path.substr(0, -4); - } + if (this.path.endsWith('.php')) { + this.path = this.path.substr(0, -4); + } - this.queryString = typeof parsed['query'] !== 'undefined' ? parsed['query'] : []; + this.queryString = typeof parsed['query'] !== 'undefined' ? parsed['query'] : []; - if (this.queryString !== null) { - this.query = jsOMS.Uri.Http.getAllUriQueryParameters(this.queryString); - } + if (this.queryString !== null) { + this.query = Http.getAllUriQueryParameters(this.queryString); + } - this.fragment = typeof parsed['fragment'] !== 'undefined' ? parsed['fragment'] : ''; - this.base = this.scheme + '://' + this.host + this.root; - }; + this.fragment = typeof parsed['fragment'] !== 'undefined' ? parsed['fragment'] : ''; + this.base = this.scheme + '://' + this.host + this.root; + }; - /** - * Set root path. - * - * @param {string} rootPath Uri root path - * - * @return {void} - * - * @since 1.0.0 - */ - setRootPath(rootPath) - { - this.root = rootPath; - this.set(this.uri); - }; + /** + * Set root path. + * + * @param {string} rootPath Uri root path + * + * @return {void} + * + * @since 1.0.0 + */ + setRootPath(rootPath) + { + this.root = rootPath; + this.set(this.uri); + }; - /** - * Get Uri base - * - * @return {string} - * - * @since 1.0.0 - */ - getBase() - { - return this.base; - }; + /** + * Get Uri base + * + * @return {string} + * + * @since 1.0.0 + */ + getBase() + { + return this.base; + }; - /** - * Get Uri scheme - * - * @return {string} - * - * @since 1.0.0 - */ - getScheme() - { - return this.scheme; - }; + /** + * Get Uri scheme + * + * @return {string} + * + * @since 1.0.0 + */ + getScheme() + { + return this.scheme; + }; - /** - * Get Uri host - * - * @return {string} - * - * @since 1.0.0 - */ - getHost() - { - return this.host; - }; + /** + * Get Uri host + * + * @return {string} + * + * @since 1.0.0 + */ + getHost() + { + return this.host; + }; - /** - * Get Uri port - * - * @return {string} - * - * @since 1.0.0 - */ - getPort() - { - return this.port; - }; + /** + * Get Uri port + * + * @return {string} + * + * @since 1.0.0 + */ + getPort() + { + return this.port; + }; - /** - * Get Uri user - * - * @return {string} - * - * @since 1.0.0 - */ - getUser() - { - return this.user; - }; + /** + * Get Uri user + * + * @return {string} + * + * @since 1.0.0 + */ + getUser() + { + return this.user; + }; - /** - * Get Uri pass - * - * @return {string} - * - * @since 1.0.0 - */ - getPass() - { - return this.pass; - }; + /** + * Get Uri pass + * + * @return {string} + * + * @since 1.0.0 + */ + getPass() + { + return this.pass; + }; - /** - * Get Uri query - * - * @return {string} - * - * @since 1.0.0 - */ - getQuery() - { - return this.queryString; - }; + /** + * Get Uri query + * + * @return {string} + * + * @since 1.0.0 + */ + getQuery() + { + return this.queryString; + }; - /** - * Get Uri - * - * @return {string} - * - * @since 1.0.0 - */ - getUri() - { - return this.uri; - }; + /** + * Get Uri + * + * @return {string} + * + * @since 1.0.0 + */ + getUri() + { + return this.uri; + }; - /** - * Get Uri fragment - * - * @return {string} - * - * @since 1.0.0 - */ - getFragment() - { - return this.fragment; - }; + /** + * Get Uri fragment + * + * @return {string} + * + * @since 1.0.0 + */ + getFragment() + { + return this.fragment; + }; - /** - * Get Uri path - * - * @return {string} - * - * @since 1.0.0 - */ - getPath() - { - return this.path; - }; + /** + * Get Uri path + * + * @return {string} + * + * @since 1.0.0 + */ + getPath() + { + return this.path; + }; - /** - * Get Uri path offset - * - * @return {int} - * - * @since 1.0.0 - */ - getPathOffset() - { - return jsOMS.substr_count(this.root, '/') - 1; - }; - } -}(window.jsOMS = window.jsOMS || {})); + /** + * Get Uri path offset + * + * @return {int} + * + * @since 1.0.0 + */ + getPathOffset() + { + return jsOMS.substr_count(this.root, '/') - 1; + }; +}; \ No newline at end of file diff --git a/Uri/UriFactory.js b/Uri/UriFactory.js index 4830035..d28ed16 100644 --- a/Uri/UriFactory.js +++ b/Uri/UriFactory.js @@ -1,3 +1,5 @@ +import { Http } from './Http.js'; + /** * Uri factory. * @@ -6,251 +8,244 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - - /** @namespace jsOMS.Uri.UriFactory */ - jsOMS.Autoloader.defineNamespace('jsOMS.Uri.UriFactory'); - - jsOMS.Uri.UriFactory = class { - /** - * Set uri query - * - * @param {string} key Query key - * @param {string} value Query value - * @param {boolean} [overwrite] Overwrite if already exists? - * - * @return {boolean} - * - * @since 1.0.0 - */ - static setQuery (key, value, overwrite) - { - overwrite = typeof overwrite !== 'undefined' ? overwrite : true; - - if (overwrite || !jsOMS.Uri.UriFactory.uri.hasOwnProperty(key)) { - jsOMS.Uri.UriFactory.uri[key] = value; - - return true; - } - - return false; - }; - - /** - * Get query - * - * @param {string} key - * - * @return {null|string} - * - * @since 1.0.0 - */ - static getQuery (key) - { - return jsOMS.Uri.UriFactory.uri.hasOwnProperty(key) ? jsOMS.Uri.UriFactory.uri[key] : null; - }; - - /** - * Clear all uri components - * - * @return {boolean} - * - * @since 1.0.0 - */ - static clearAll () - { - jsOMS.Uri.UriFactory.uri = {}; - - return true; - }; - - /** - * Clear uri component - * - * @param {string} key Uri key for component - * - * @return {boolean} - * - * @since 1.0.0 - */ - static clear (key) - { - if (jsOMS.Uri.UriFactory.uri.hasOwnProperty(key)) { - delete jsOMS.Uri.UriFactory.uri[key]; - - return true; - } - - return false; - }; - - /** - * Clear uri components that follow a certain pattern - * - * @param {string} pattern Uri key pattern to remove - * - * @return {boolean} - * - * @since 1.0.0 - */ - static clearLike (pattern) - { - let success = false; - const regexp = new RegExp(pattern); - - for (let key in jsOMS.Uri.UriFactory.uri) { - if (jsOMS.Uri.UriFactory.uri.hasOwnProperty(key) && regexp.test(key)) { - delete jsOMS.Uri.UriFactory.uri[key]; - success = true; - } - } - - return success; - }; - - /** - * Remove multiple definitions of the same parameter - * - * The parameters will be recognized from right to left since it's easier to push at the end. - * - * @param {string} url Url - * - * @return {string} - * - * @since 1.0.0 - */ - static unique (url) - { - // unique queries - const parts = url.replace(/\?/g, '&').split('&'), - full = parts[0]; - - if (parts.length > 1) { - parts.shift(); - - let comps = {}, - spl = null, - length = parts.length; - - for (let i = 0; i < length; ++i) { - spl = parts[i].split('='); - comps[spl[0]] = spl[1]; - } - - let pars = []; - for (let a in comps) { - if (comps.hasOwnProperty(a)) { - pars.push(a + '=' + comps[a]); - } - } - - url = full + '?' + pars.join('&'); - } - - // unique fragments - const fragments = url.match(/\#[a-zA-Z0-9\-,]+/g), - fragLength = fragments !== null ? fragments.length : 0; - - for (let i = 0; i < fragLength - 1; ++i) { - // remove all from old url - url = url.replace(fragments[i], ''); - } - - return url; - }; - - /** - * Build uri - * - * # = DOM id - * . = DOM class - * / = Current path - * ? = Current query - * @ = - * $ = Other data - * % = Current url - * - * @param {string} uri Raw uri - * @param {Object} [toMatch] Key/value pair to replace in raw - * - * @return {string} - * - * @since 1.0.0 - */ - static build (uri, toMatch) - { - const current = jsOMS.Uri.Http.parseUrl(window.location.href); - let parsed = uri.replace(new RegExp('\{[\/#\?%@\.\$][a-zA-Z0-9\-]*\}', 'g'), function (match) - { - match = match.substr(1, match.length - 2); - - if (typeof toMatch !== 'undefined' && toMatch.hasOwnProperty(match)) { - return toMatch[match]; - } else if (typeof jsOMS.Uri.UriFactory.uri[match] !== 'undefined') { - return jsOMS.Uri.UriFactory.uri[match]; - } else if (match.indexOf('#') === 0) { - const e = document.getElementById(match.substr(1)); - - if (e) { - return e.value; - } - - return ''; - } else if (match.indexOf('?') === 0) { - return jsOMS.Uri.Http.getUriQueryParameter(current.query, match.substr(1)); - } else if (match.indexOf('/') === 0) { - // todo: second match should return second path - return 'ERROR PATH'; - } else if (match === '%') { - return window.location.href; - } else { - return match; - } - }); - - if (parsed.indexOf('?') === -1) { - parsed = parsed.replace('&', '?'); - } - - return jsOMS.Uri.UriFactory.unique(parsed); - }; - - /** - * Set uri builder components. - * - * @return {void} - * - * @since 1.0.0 - */ - static setupUriBuilder (uri) - { - jsOMS.Uri.UriFactory.setQuery('/scheme', uri.getScheme()); - jsOMS.Uri.UriFactory.setQuery('/host', uri.getHost()); - jsOMS.Uri.UriFactory.setQuery('/base', jsOMS.rtrim(uri.getBase(), '/')); - jsOMS.Uri.UriFactory.setQuery('?', uri.getQuery()); - jsOMS.Uri.UriFactory.setQuery('%', uri.getUri()); - jsOMS.Uri.UriFactory.setQuery('#', uri.getFragment()); - jsOMS.Uri.UriFactory.setQuery('/', uri.getPath()); - jsOMS.Uri.UriFactory.setQuery(':user', uri.getUser()); - jsOMS.Uri.UriFactory.setQuery(':pass', uri.getPass()); - - const query = uri.getQuery(); - - for (let key in query) { - if (query.hasOwnProperty(key)) { - jsOMS.Uri.UriFactory.setQuery('?' + key, query[key]); - } - } - }; - } - +export class UriFactory { /** - * Uri values + * Set uri query + * + * @param {string} key Query key + * @param {string} value Query value + * @param {boolean} [overwrite] Overwrite if already exists? + * + * @return {boolean} * - * @var {Object} * @since 1.0.0 */ - jsOMS.Uri.UriFactory.uri = {}; -}(window.jsOMS = window.jsOMS || {})); + static setQuery (key, value, overwrite) + { + overwrite = typeof overwrite !== 'undefined' ? overwrite : true; + + if (overwrite || !UriFactory.uri.hasOwnProperty(key)) { + UriFactory.uri[key] = value; + + return true; + } + + return false; + }; + + /** + * Get query + * + * @param {string} key + * + * @return {null|string} + * + * @since 1.0.0 + */ + static getQuery (key) + { + return UriFactory.uri.hasOwnProperty(key) ? UriFactory.uri[key] : null; + }; + + /** + * Clear all uri components + * + * @return {boolean} + * + * @since 1.0.0 + */ + static clearAll () + { + UriFactory.uri = {}; + + return true; + }; + + /** + * Clear uri component + * + * @param {string} key Uri key for component + * + * @return {boolean} + * + * @since 1.0.0 + */ + static clear (key) + { + if (UriFactory.uri.hasOwnProperty(key)) { + delete UriFactory.uri[key]; + + return true; + } + + return false; + }; + + /** + * Clear uri components that follow a certain pattern + * + * @param {string} pattern Uri key pattern to remove + * + * @return {boolean} + * + * @since 1.0.0 + */ + static clearLike (pattern) + { + let success = false; + const regexp = new RegExp(pattern); + + for (let key in UriFactory.uri) { + if (UriFactory.uri.hasOwnProperty(key) && regexp.test(key)) { + delete UriFactory.uri[key]; + success = true; + } + } + + return success; + }; + + /** + * Remove multiple definitions of the same parameter + * + * The parameters will be recognized from right to left since it's easier to push at the end. + * + * @param {string} url Url + * + * @return {string} + * + * @since 1.0.0 + */ + static unique (url) + { + // unique queries + const parts = url.replace(/\?/g, '&').split('&'), + full = parts[0]; + + if (parts.length > 1) { + parts.shift(); + + let comps = {}, + spl = null, + length = parts.length; + + for (let i = 0; i < length; ++i) { + spl = parts[i].split('='); + comps[spl[0]] = spl[1]; + } + + let pars = []; + for (let a in comps) { + if (comps.hasOwnProperty(a)) { + pars.push(a + '=' + comps[a]); + } + } + + url = full + '?' + pars.join('&'); + } + + // unique fragments + const fragments = url.match(/\#[a-zA-Z0-9\-,]+/g), + fragLength = fragments !== null ? fragments.length : 0; + + for (let i = 0; i < fragLength - 1; ++i) { + // remove all from old url + url = url.replace(fragments[i], ''); + } + + return url; + }; + + /** + * Build uri + * + * # = DOM id + * . = DOM class + * / = Current path + * ? = Current query + * @ = + * $ = Other data + * % = Current url + * + * @param {string} uri Raw uri + * @param {Object} [toMatch] Key/value pair to replace in raw + * + * @return {string} + * + * @since 1.0.0 + */ + static build (uri, toMatch) + { + const current = Http.parseUrl(window.location.href); + let parsed = uri.replace(new RegExp('\{[\/#\?%@\.\$][a-zA-Z0-9\-]*\}', 'g'), function (match) + { + match = match.substr(1, match.length - 2); + + if (typeof toMatch !== 'undefined' && toMatch.hasOwnProperty(match)) { + return toMatch[match]; + } else if (typeof UriFactory.uri[match] !== 'undefined') { + return UriFactory.uri[match]; + } else if (match.indexOf('#') === 0) { + const e = document.getElementById(match.substr(1)); + + if (e) { + return e.value; + } + + return ''; + } else if (match.indexOf('?') === 0) { + return Http.getUriQueryParameter(current.query, match.substr(1)); + } else if (match.indexOf('/') === 0) { + // todo: second match should return second path + return 'ERROR PATH'; + } else if (match === '%') { + return window.location.href; + } else { + return match; + } + }); + + if (parsed.indexOf('?') === -1) { + parsed = parsed.replace('&', '?'); + } + + return UriFactory.unique(parsed); + }; + + /** + * Set uri builder components. + * + * @return {void} + * + * @since 1.0.0 + */ + static setupUriBuilder (uri) + { + UriFactory.setQuery('/scheme', uri.getScheme()); + UriFactory.setQuery('/host', uri.getHost()); + UriFactory.setQuery('/base', jsOMS.rtrim(uri.getBase(), '/')); + UriFactory.setQuery('?', uri.getQuery()); + UriFactory.setQuery('%', uri.getUri()); + UriFactory.setQuery('#', uri.getFragment()); + UriFactory.setQuery('/', uri.getPath()); + UriFactory.setQuery(':user', uri.getUser()); + UriFactory.setQuery(':pass', uri.getPass()); + + const query = uri.getQuery(); + + for (let key in query) { + if (query.hasOwnProperty(key)) { + UriFactory.setQuery('?' + key, query[key]); + } + } + }; +}; + +/** + * Uri values + * + * @var {Object} + * @since 1.0.0 + */ +UriFactory.uri = {}; + diff --git a/Views/FormView.js b/Views/FormView.js index c2a5f14..61bc8bc 100644 --- a/Views/FormView.js +++ b/Views/FormView.js @@ -10,462 +10,455 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) -{ - "use strict"; - /** @namespace jsOMS.Views */ - jsOMS.Autoloader.defineNamespace('jsOMS.Views'); +export class FormView { + /** + * @constructor + * + * @param {string} id Form id + * + * @since 1.0.0 + */ + constructor (id) + { + this.id = id; - jsOMS.Views.FormView = class { - /** - * @constructor - * - * @param {string} id Form id - * - * @since 1.0.0 - */ - constructor (id) - { - this.id = id; + this.initializeMembers(); + this.bind(); - this.initializeMembers(); - this.bind(); + this.success = null; + this.finally = null; + this.lastSubmit = 0; + }; - this.success = null; - this.finally = null; - this.lastSubmit = 0; - }; + /** + * Initialize members + * + * Pulled out since this is used in a cleanup process + * + * @return {void} + * + * @since 1.0.0 + */ + initializeMembers () + { + this.submitInjects = []; + this.method = 'POST'; + this.action = ''; + }; - /** - * Initialize members - * - * Pulled out since this is used in a cleanup process - * - * @return {void} - * - * @since 1.0.0 - */ - initializeMembers () - { - this.submitInjects = []; - this.method = 'POST'; - this.action = ''; - }; + /** + * Get method + * + * @return {string} + * + * @since 1.0.0 + */ + getMethod () + { + return this.method; + }; - /** - * Get method - * - * @return {string} - * - * @since 1.0.0 - */ - getMethod () - { - return this.method; - }; + /** + * Get action + * + * @return {string} + * + * @since 1.0.0 + */ + getAction () + { + return this.action; + }; - /** - * Get action - * - * @return {string} - * - * @since 1.0.0 - */ - getAction () - { - return this.action; - }; + /** + * Get time of last submit + * + * @return {int} + * + * @since 1.0.0 + */ + getLastSubmit () + { + return this.lastSubmit; + }; - /** - * Get time of last submit - * - * @return {int} - * - * @since 1.0.0 - */ - getLastSubmit () - { - return this.lastSubmit; - }; + /** + * Update last submit time + * + * @return {void} + * + * @since 1.0.0 + */ + updateLastSubmit () + { + this.lastSubmit = Math.floor(Date.now()); + }; - /** - * Update last submit time - * - * @return {void} - * - * @since 1.0.0 - */ - updateLastSubmit () - { - this.lastSubmit = Math.floor(Date.now()); - }; + /** + * Get submit elements + * + * @return {Object} + * + * @since 1.0.0 + */ + getSubmit () + { + return document.querySelectorAll( + '#' + this.id + ' input[type=submit], ' + + 'button[form=' + this.id + '][type=submit], ' + + '#' + this.id + ' button[type=submit], ' + + '#' + this.id + ' .submit' + ); + }; - /** - * Get submit elements - * - * @return {Object} - * - * @since 1.0.0 - */ - getSubmit () - { - return document.querySelectorAll( - '#' + this.id + ' input[type=submit], ' - + 'button[form=' + this.id + '][type=submit], ' - + '#' + this.id + ' button[type=submit], ' - + '#' + this.id + ' .submit' - ); - }; + /** + * Get success callback + * + * @return {callback} + * + * @since 1.0.0 + */ + getSuccess () + { + return this.success; + }; - /** - * Get success callback - * - * @return {callback} - * - * @since 1.0.0 - */ - getSuccess () - { - return this.success; - }; + /** + * Set success callback + * + * @param {callback} callback Callback + * + * @return {void} + * + * @since 1.0.0 + */ + setSuccess (callback) + { + this.success = callback; + }; - /** - * Set success callback - * - * @param {callback} callback Callback - * - * @return {void} - * - * @since 1.0.0 - */ - setSuccess (callback) - { - this.success = callback; - }; + /** + * Get finally callback + * + * @return {callback} + * + * @since 1.0.0 + */ + getFinally() { + return this.finally; + }; - /** - * Get finally callback - * - * @return {callback} - * - * @since 1.0.0 - */ - getFinally() { - return this.finally; - }; + /** + * Set finally callback + * + * @param {callback} callback Callback + * + * @return {void} + * + * @since 1.0.0 + */ + setFinally(callback) { + this.finally = callback; + }; - /** - * Set finally callback - * - * @param {callback} callback Callback - * - * @return {void} - * - * @since 1.0.0 - */ - setFinally(callback) { - this.finally = callback; - }; + /** + * Inject submit with post callback + * + * @param {callback} callback Callback + * + * @return {void} + * + * @since 1.0.0 + */ + injectSubmit (callback) + { + this.submitInjects.push(callback); + }; - /** - * Inject submit with post callback - * - * @param {callback} callback Callback - * - * @return {void} - * - * @since 1.0.0 - */ - injectSubmit (callback) - { - this.submitInjects.push(callback); - }; + /** + * Get form elements + * + * @return {Array} + * + * @since 1.0.0 + */ + getFormElements () + { + const form = document.getElementById(this.id); - /** - * Get form elements - * - * @return {Array} - * - * @since 1.0.0 - */ - getFormElements () - { - const form = document.getElementById(this.id); + if (!form) { + return []; + } - if (!form) { - return []; + const selects = form.getElementsByTagName('select'), + textareas = form.getElementsByTagName('textarea'), + inputs = [].slice.call(form.getElementsByTagName('input')), + buttons = form.getElementsByTagName('button'), + canvas = form.getElementsByTagName('canvas'), + external = document.querySelectorAll('[form=' + this.id + ']'), + special = form.querySelectorAll('[data-name]'), + specialExt = document.querySelectorAll('[data-form=' + this.id + '] [data-name]'), + inputLength = inputs.length; + + // todo: handle trigger element. check which element triggered the submit and pass it's name+value + // the reason for this is, there may be multiple buttons in a form which trigger a send + // sometimes even a checkbox or drop down could trigger a send + // Maybe it makes sense to do this however at a different place e.g. the actual data submit + + for (let i = 0; i < inputLength; ++i) { + if (inputs[i].type === 'checkbox' && !inputs[i].checked) { + delete inputs[i]; } - const selects = form.getElementsByTagName('select'), - textareas = form.getElementsByTagName('textarea'), - inputs = [].slice.call(form.getElementsByTagName('input')), - buttons = form.getElementsByTagName('button'), - canvas = form.getElementsByTagName('canvas'), - external = document.querySelectorAll('[form=' + this.id + ']'), - special = form.querySelectorAll('[data-name]'), - specialExt = document.querySelectorAll('[data-form=' + this.id + '] [data-name]'), - inputLength = inputs.length; + // todo: handle radio here as well + } - // todo: handle trigger element. check which element triggered the submit and pass it's name+value - // the reason for this is, there may be multiple buttons in a form which trigger a send - // sometimes even a checkbox or drop down could trigger a send - // Maybe it makes sense to do this however at a different place e.g. the actual data submit + return Array.prototype.slice.call(inputs).concat( + Array.prototype.slice.call(selects), + Array.prototype.slice.call(textareas), + Array.prototype.slice.call(buttons), + Array.prototype.slice.call(external), + Array.prototype.slice.call(special), + Array.prototype.slice.call(specialExt) + ).filter(function(val) { return val; }); + }; - for (let i = 0; i < inputLength; ++i) { - if (inputs[i].type === 'checkbox' && !inputs[i].checked) { - delete inputs[i]; + /** + * Get unique form elements + * + * @param {Array} arr Form element array + * + * @return {Array} + * + * @since 1.0.0 + */ + getUniqueFormElements (arr) + { + let seen = {}; + + return arr.filter(function(item) { + return seen.hasOwnProperty(item.name) ? false : (seen[item.name] = true); + }); + }; + + /** + * Get form data + * + * @return {Object} + * + * @since 1.0.0 + */ + getData () + { + const data = {}, + elements = this.getFormElements(), + length = elements.length; + + let value = null; + + for (let i = 0; i < length; ++i) { + if (elements[i].tagName.toLowerCase() === 'canvas') { + value = elements[i].toDataURL('image/png'); + } else { + if (typeof elements[i].value !== 'undefined') { + value = elements[i].value; + } else if (typeof elements[i].getAttribute('data-value') !== 'undefined') { + value = elements[i].getAttribute('data-value'); + } + } + + const id = jsOMS.Views.FormView.getElementId(elements[i]); + if (id === null) { + continue; + } + + // handle array data (e.g. table rows with same name) + if (data.hasOwnProperty(id)) { + if (data[id].constructor !== Array) { + data[id] = [data[id]]; } - // todo: handle radio here as well + data[id].push(value); + } else { + data[id] = value; } + } - return Array.prototype.slice.call(inputs).concat( - Array.prototype.slice.call(selects), - Array.prototype.slice.call(textareas), - Array.prototype.slice.call(buttons), - Array.prototype.slice.call(external), - Array.prototype.slice.call(special), - Array.prototype.slice.call(specialExt) - ).filter(function(val) { return val; }); - }; + return data; + }; - /** - * Get unique form elements - * - * @param {Array} arr Form element array - * - * @return {Array} - * - * @since 1.0.0 - */ - getUniqueFormElements (arr) - { - let seen = {}; + /** + * Get form id + * + * @return {string} + * + * @since 1.0.0 + */ + getId () + { + return this.id; + }; - return arr.filter(function(item) { - return seen.hasOwnProperty(item.name) ? false : (seen[item.name] = true); - }); - }; - - /** - * Get form data - * - * @return {Object} - * - * @since 1.0.0 - */ - getData () - { - const data = {}, - elements = this.getFormElements(), - length = elements.length; - - let value = null; + /** + * Validate form + * + * @return {boolean} + * + * @since 1.0.0 + */ + isValid () + { + const elements = this.getFormElements(), + length = elements.length; + try { for (let i = 0; i < length; ++i) { - if (elements[i].tagName.toLowerCase() === 'canvas') { - value = elements[i].toDataURL('image/png'); - } else { - if (typeof elements[i].value !== 'undefined') { - value = elements[i].value; - } else if (typeof elements[i].getAttribute('data-value') !== 'undefined') { - value = elements[i].getAttribute('data-value'); - } - } - - const id = jsOMS.Views.FormView.getElementId(elements[i]); - if (id === null) { - continue; - } - - // handle array data (e.g. table rows with same name) - if (data.hasOwnProperty(id)) { - if (data[id].constructor !== Array) { - data[id] = [data[id]]; - } - - data[id].push(value); - } else { - data[id] = value; + if ((elements[i].required && elements[i].value === '') + || (typeof elements[i].pattern !== 'undefined' + && elements[i].pattern !== '' + && !(new RegExp(elements[i].pattern)).test(elements[i].value)) + ) { + return false; } } + } catch (e) { + jsOMS.Log.Logger.instance.error(e); + } - return data; - }; + return true; + }; - /** - * Get form id - * - * @return {string} - * - * @since 1.0.0 - */ - getId () - { - return this.id; - }; + /** + * Get form element + * + * @return {Object} + * + * @since 1.0.0 + */ + getElement () + { + return document.getElementById(this.getId()); + }; - /** - * Validate form - * - * @return {boolean} - * - * @since 1.0.0 - */ - isValid () - { - const elements = this.getFormElements(), - length = elements.length; + /** + * Get form element id + * + * @return {string} + * + * @since 1.0.0 + */ + static getElementId (e) + { + if (e.getAttribute('name') !== null) { + return e.getAttribute('name'); + } else if (e.getAttribute('id') !== null) { + return e.getAttribute('id'); + } else if (e.getAttribute('data-name') !== null) { + return e.getAttribute('data-name'); + } else if (e.getAttribute('type') !== null) { + return e.getAttribute('type'); + } - try { - for (let i = 0; i < length; ++i) { - if ((elements[i].required && elements[i].value === '') - || (typeof elements[i].pattern !== 'undefined' - && elements[i].pattern !== '' - && !(new RegExp(elements[i].pattern)).test(elements[i].value)) - ) { - return false; - } - } - } catch (e) { - jsOMS.Log.Logger.instance.error(e); + return null; + }; + + /** + * Get submit injects + * + * @return {Object} + * + * @since 1.0.0 + */ + getSubmitInjects () + { + return this.submitInjects; + }; + + /** + * Bind form + * + * @return {void} + * + * @since 1.0.0 + * @todo: check bind functionality maybe remove!!! + */ + bind () + { + this.clean(); + + const e = document.getElementById(this.id); + + if (!e) { + return; + } + + this.method = typeof e.attributes['method'] !== 'undefined' ? e.attributes['method'].value : 'EMPTY'; + this.action = typeof e.action !== 'undefined' ? e.action : 'EMPTY'; + + const elements = this.getFormElements(), + length = elements.length; + + for (let i = 0; i < length; ++i) { + switch (elements[i].tagName) { + case 'input': + jsOMS.UI.Input.bind(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: } + } + }; - return true; - }; + /** + * Unbind form + * + * @return {void} + * + * @since 1.0.0 + * @todo: check unbind functionality maybe remove = everything!!! + */ + unbind () + { + const elements = this.getFormElements(), + length = elements.length; - /** - * Get form element - * - * @return {Object} - * - * @since 1.0.0 - */ - getElement () - { - return document.getElementById(this.getId()); - }; - - /** - * Get form element id - * - * @return {string} - * - * @since 1.0.0 - */ - static getElementId (e) - { - if (e.getAttribute('name') !== null) { - return e.getAttribute('name'); - } else if (e.getAttribute('id') !== null) { - return e.getAttribute('id'); - } else if (e.getAttribute('data-name') !== null) { - return e.getAttribute('data-name'); - } else if (e.getAttribute('type') !== null) { - return e.getAttribute('type'); + for (let i = 0; i < length; ++i) { + switch (elements[i].tagName) { + case 'input': + jsOMS.UI.Input.unbind(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: } + } + }; - return null; - }; - - /** - * Get submit injects - * - * @return {Object} - * - * @since 1.0.0 - */ - getSubmitInjects () - { - return this.submitInjects; - }; - - /** - * Bind form - * - * @return {void} - * - * @since 1.0.0 - * @todo: check bind functionality maybe remove!!! - */ - bind () - { - this.clean(); - - const e = document.getElementById(this.id); - - if (!e) { - return; - } - - this.method = typeof e.attributes['method'] !== 'undefined' ? e.attributes['method'].value : 'EMPTY'; - this.action = typeof e.action !== 'undefined' ? e.action : 'EMPTY'; - - const elements = this.getFormElements(), - length = elements.length; - - for (let i = 0; i < length; ++i) { - switch (elements[i].tagName) { - case 'input': - jsOMS.UI.Input.bind(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: - } - } - }; - - /** - * Unbind form - * - * @return {void} - * - * @since 1.0.0 - * @todo: check unbind functionality maybe remove = everything!!! - */ - unbind () - { - const elements = this.getFormElements(), - length = elements.length; - - for (let i = 0; i < length; ++i) { - switch (elements[i].tagName) { - case 'input': - jsOMS.UI.Input.unbind(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: - } - } - }; - - /** - * Clean form - * - * @return {void} - * - * @since 1.0.0 - */ - clean () - { - this.unbind(); - this.initializeMembers(); - }; - } -}(window.jsOMS = window.jsOMS || {})); + /** + * Clean form + * + * @return {void} + * + * @since 1.0.0 + */ + clean () + { + this.unbind(); + this.initializeMembers(); + }; +}; diff --git a/Views/TableView.js b/Views/TableView.js index 5bc894b..9091de7 100644 --- a/Views/TableView.js +++ b/Views/TableView.js @@ -6,157 +6,151 @@ * @version 1.0.0 * @since 1.0.0 */ -(function (jsOMS) { - "use strict"; +export class TableView { + /** + * @constructor + * + * @since 1.0.0 + */ + constructor (id) { + this.id = id; - jsOMS.Autoloader.defineNamespace('jsOMS.Views'); + this.bind(); + }; - jsOMS.Views.TableView = class { - /** - * @constructor - * - * @since 1.0.0 - */ - constructor (id) { - this.id = id; + /** + * Bind the table + * + * @return {void} + * + * @since 1.0.0 + */ + bind () + { + const e = document.getElementById(this.id); + }; - this.bind(); + /** + * Serialize table data + * + * @return {object} + * + * @since 1.0.0 + */ + serialize() + { + const table = document.getElementById(this.id); + let data = { + caption: null, + header: [], + rows: [] }; - /** - * Bind the table - * - * @return {void} - * - * @since 1.0.0 - */ - bind () - { - const e = document.getElementById(this.id); - }; + data.caption = table.getElementsByTagName('caption')[0].innerText; - /** - * Serialize table data - * - * @return {object} - * - * @since 1.0.0 - */ - serialize() - { - const table = document.getElementById(this.id); - let data = { - caption: null, - header: [], - rows: [] - }; + const header = table.querySelectorAll('thead tr td, thead tr th'), + headerLength = header.length; - data.caption = table.getElementsByTagName('caption')[0].innerText; - - const header = table.querySelectorAll('thead tr td, thead tr th'), - headerLength = header.length; - - for (let i = 0; i < headerLength; ++i) { - data.header.push(header[i].innerText); - } - - const rows = table.querySelectorAll('tbody tr'), - rowsLength = rows.length; - - for (let i = 0; i < rowsLength; ++i) { - data.rows[i] = []; - - const columns = rows[i].querySelectorAll('td, th'), - columnLength = columns.length; - - for (let j = 0; j < columnLength; ++j) { - data.rows[i].push(columns[j].innerText); - } - } - - return data; + for (let i = 0; i < headerLength; ++i) { + data.header.push(header[i].innerText); } - /** - * Get table export button - * - * @return {HTMLElement} - * - * @since 1.0.0 - */ - getExport() - { - return document.querySelectorAll('#' + this.id + ' .download')[0]; - }; + const rows = table.querySelectorAll('tbody tr'), + rowsLength = rows.length; - /** - * Get table header elements which provide sorting - * - * @return {array} - * - * @since 1.0.0 - */ - getSorting() - { - return document.querySelectorAll( - '#' + this.id + ' thead .sort-asc,' - + ' #' + this.id + ' thead .sort-desc' - ); - }; + for (let i = 0; i < rowsLength; ++i) { + data.rows[i] = []; - /** - * Get table header elements which provide filter functionality - * - * @return {array} - * - * @since 1.0.0 - */ - getFilter() - { - return document.querySelectorAll( - '#' + this.id + ' thead .filter' - ); - }; + const columns = rows[i].querySelectorAll('td, th'), + columnLength = columns.length; - /** - * Get row elements which allow to swap the current row with another row - * - * @return {array} - * - * @since 1.0.0 - */ - getSortableRows() - { - return document.querySelectorAll( - '#' + this.id + ' tbody .order-up,' - + ' #' + this.id + ' tbody .order-down' - ); - }; + for (let j = 0; j < columnLength; ++j) { + data.rows[i].push(columns[j].innerText); + } + } - /** - * Get row elements which allow to remove a row element - * - * @return {array} - * - * @since 1.0.0 - */ - getRemovable() - { - return document.querySelectorAll( - '#' + this.id + ' tbody .remove' - ); - }; - - getForm() - { - return document.getElementById(this.id).getAttribute('data-table-form'); - }; - - getUpdatable() - { - return document.querySelectorAll( - '#' + this.id + ' tbody .update' - ); - }; + return data; } -}(window.jsOMS = window.jsOMS || {})); + + /** + * Get table export button + * + * @return {HTMLElement} + * + * @since 1.0.0 + */ + getExport() + { + return document.querySelectorAll('#' + this.id + ' .download')[0]; + }; + + /** + * Get table header elements which provide sorting + * + * @return {array} + * + * @since 1.0.0 + */ + getSorting() + { + return document.querySelectorAll( + '#' + this.id + ' thead .sort-asc,' + + ' #' + this.id + ' thead .sort-desc' + ); + }; + + /** + * Get table header elements which provide filter functionality + * + * @return {array} + * + * @since 1.0.0 + */ + getFilter() + { + return document.querySelectorAll( + '#' + this.id + ' thead .filter' + ); + }; + + /** + * Get row elements which allow to swap the current row with another row + * + * @return {array} + * + * @since 1.0.0 + */ + getSortableRows() + { + return document.querySelectorAll( + '#' + this.id + ' tbody .order-up,' + + ' #' + this.id + ' tbody .order-down' + ); + }; + + /** + * Get row elements which allow to remove a row element + * + * @return {array} + * + * @since 1.0.0 + */ + getRemovable() + { + return document.querySelectorAll( + '#' + this.id + ' tbody .remove' + ); + }; + + getForm() + { + return document.getElementById(this.id).getAttribute('data-table-form'); + }; + + getUpdatable() + { + return document.querySelectorAll( + '#' + this.id + ' tbody .update' + ); + }; +};