Use js modules

This commit is contained in:
Dennis Eichhorn 2019-04-02 22:46:48 +02:00
parent b40c6670d4
commit 89acb321f9
76 changed files with 5341 additions and 5668 deletions

View File

@ -6,33 +6,26 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class Account {
{ /**
"use strict"; * @constructor
*
jsOMS.Autoloader.defineNamespace('jsOMS.Account'); * @since 1.0.0
*/
jsOMS.Account.Account = class { constructor ()
/** {
* @constructor this.id = 0;
*
* @since 1.0.0
*/
constructor ()
{
this.id = 0;
};
/**
* Get id.
*
* @return {int}
*
* @since 1.0.0
*/
getId ()
{
return this.id;
};
}; };
}(window.jsOMS = window.jsOMS || {}));
/**
* Get id.
*
* @return {int}
*
* @since 1.0.0
*/
getId ()
{
return this.id;
};
};

View File

@ -6,73 +6,66 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class AccountManager {
{ /**
"use strict"; * @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 { /**
/** * Remove account.
* @constructor *
* * @param {int} id Account id
* @since 1.0.0 *
*/ * @return {void}
constructor () *
{ * @since 1.0.0
this.accounts = []; */
}; remove (id)
{
if (typeof this.accounts[id] !== 'undefined') {
delete this.accounts[id];
/** return true;
* Add account. }
*
* @param {Object} account Account
*
* @return {void}
*
* @since 1.0.0
*/
add (account)
{
this.accounts[account.getId()] = account;
};
/** return false;
* 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 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; return null;
}; };
};
/**
* 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 || {}));

View File

@ -6,14 +6,7 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const AccountType = Object.freeze({
{ USER: 0,
"use strict"; GROUP: 1
});
jsOMS.Autoloader.defineNamespace('jsOMS.Account');
jsOMS.Account.AccountType = Object.freeze({
USER: 0,
GROUP: 1
});
}(window.jsOMS = window.jsOMS || {}));

View File

@ -6,157 +6,151 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class AssetManager {
{ /**
"use strict"; * @constructor
*
jsOMS.Asset = {}; * @since 1.0.0
*/
jsOMS.Asset.AssetManager = class { constructor ()
/** {
* @constructor this.assets = {};
* this.registerLoadedAssets();
* @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;
};
}; };
}(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;
};
};

View File

@ -6,95 +6,88 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class Auth {
{ /**
"use strict"; * @constructor
*
jsOMS.Autoloader.defineNamespace('jsOMS.Auth'); * @param {string} uri Login uri
*
jsOMS.Auth.Auth = class { * @since 1.0.0
/** */
* @constructor constructor (uri)
* {
* @param {string} uri Login uri this.account = null;
* this.uri = 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();
};
}; };
}(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();
};
};

View File

@ -1,3 +1,5 @@
import { AssetManager } from './Asset/AssetManager.js';
/** /**
* Autoloader. * Autoloader.
* *
@ -11,108 +13,104 @@
* @version 1.0.0 * @version 1.0.0
* @since 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 = {}; const length = paths.length;
jsOMS.Autoloader.loaded = []; let current = jsOMS;
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;
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
/** global: URL */ if (typeof current[paths[i]] === 'undefined') {
/** @var {string} URL */ current[paths[i]] = {};
scripts[i].src.replace(URL + '/', '');
if (jsOMS.Autoloader.loaded.indexOf(scripts[i].src) === -1) {
jsOMS.Autoloader.loaded.push(scripts[i].src);
} }
}
};
/** current = 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);
}
} }
if (typeof callback !== 'undefined' && callback !== null) { Autoloader.namespaced.push(namespace);
callback(); }
};
/**
* 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 || {})); };
/**
* 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();
}
};

View File

@ -1,14 +1,6 @@
(function (jsOMS) { export class CacheManager {
"use strict"; constructor ()
{
jsOMS.Autoloader.defineNamespace('jsOMS.DataStorage'); }
};
// TODO: create comments
jsOMS.DataStorage.CacheManager = class {
constructor ()
{
}
};
}(window.jsOMS = window.jsOMS || {}));

View File

@ -6,36 +6,29 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class LocalStorage {
{ /**
"use strict"; * @constructor
*
jsOMS.Autoloader.defineNamespace('jsOMS.DataStorage'); * @since 1.0.0
*/
jsOMS.DataStorage.LocalStorage = class { constructor ()
/** {
* @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;
}
};
}; };
}(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;
}
};
};

View File

@ -1,11 +1,5 @@
(function (jsOMS) { export class StorageManager {
"use strict"; constructor ()
{
jsOMS.Autoloader.defineNamespace('jsOMS.DataStorage'); };
};
jsOMS.DataStorage.StorageManager = class {
constructor ()
{
};
}
}(window.jsOMS = window.jsOMS || {}));

View File

@ -1,11 +1,5 @@
(function (jsOMS) { export class Dispatcher {
"use strict"; constructor ()
{
jsOMS.Autoloader.defineNamespace('jsOMS.Dispatcher'); };
};
jsOMS.Dispatcher.Dispatcher = class {
constructor ()
{
};
}
}(window.jsOMS = window.jsOMS || {}));

View File

@ -1,3 +1,5 @@
import { Logger } from '../Log/Logger.js';
/** /**
* Request manager class. * Request manager class.
* *
@ -8,252 +10,245 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class EventManager {
{ /**
"use strict"; * @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 { this.groups[group][id] = false;
/** };
* @constructor
*
* @since 1.0.0
*/
constructor ()
{
this.logger = jsOMS.Log.Logger.getInstance();
this.groups = {};
this.callbacks = {};
};
/** /**
* Add event group (element) * Resets the group status
* *
* Adding the same event overwrites the existing one as "waiting" * @param {string|int} group Group id
* *
* @param {string|int} group Group id * @return {void}
* @param {string|int} id Event id *
* * @since 1.0.0
* @return {void} */
* reset (group)
* @since 1.0.0 {
*/ for (let id in this.groups[group]) {
addGroup (group, id) if (this.groups[group].hasOwnProperty(id)) {
{ this.groups[group][id] = false;
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;
}
} }
}
};
/**
* 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; return false;
}; }
/** for (let id in this.groups[group]) {
* Trigger event finished if (!this.groups[group].hasOwnProperty(id) || !this.groups[group][id]) {
* return true;
* 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), return false;
regex = new RegExp(group), };
length = allGroups.length;
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) { for (let i = 0; i < length; ++i) {
if (regex.test(allGroups[i])) { this.callbacks[group].callbacks[i](data);
result = result && this.triggerSingleEvent(allGroups[i], id, data);
}
} }
return result; if (this.callbacks[group].remove) {
}; this.detach(group);
} else if (this.callbacks[group].reset) {
/** this.reset(group);
* 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) {
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; return true;
}; }
/** return false;
* Count events };
*
* @return {int} /**
* * Detach event
* @since 1.0.0 *
*/ * @param {string|int} group Group id
count () *
{ * @return {void}
return Object.keys(this.callbacks).length; *
}; * @since 1.0.0
} */
}(window.jsOMS = window.jsOMS || {})); 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;
};
};

View File

@ -6,21 +6,13 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const LogLevel = Object.freeze({
{ EMERGENCY: 'emergency',
"use strict"; ALERT: 'alert',
CRITICAL: 'critical',
/** @namespace jsOMS.Log */ ERROR: 'error',
jsOMS.Autoloader.defineNamespace('jsOMS.Log'); WARNING: 'warning',
NOTICE: 'notice',
jsOMS.Log.LogLevel = Object.freeze({ INFO: 'info',
EMERGENCY: 'emergency', DEBUG: 'debug'
ALERT: 'alert', });
CRITICAL: 'critical',
ERROR: 'error',
WARNING: 'warning',
NOTICE: 'notice',
INFO: 'info',
DEBUG: 'debug'
});
}(window.jsOMS = window.jsOMS || {}));

View File

@ -1,3 +1,6 @@
import { LogLevel } from './LogLevel.js';
import { Request } from '../Message/Request/Request.js';
/** /**
* Logger class. * Logger class.
* *
@ -6,341 +9,334 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class Logger {
{ /**
"use strict"; * @constructor
/** @namespace jsOMS.Log */ *
jsOMS.Autoloader.defineNamespace('jsOMS.Log'); * @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 { /**
/** * Get logging instance
* @constructor *
* * @param {boolean} [verbose] Verbose logging
* @param {boolean} verbose Verbose logging * @param {boolean} [ui] Ui logging
* @param {boolean} ui Ui logging * @param {boolean} [remote] Remote logging
* @param {boolean} remote Remote logging *
* * @return {Object}
* @since 1.0.0 *
*/ * @since 1.0.0
constructor (verbose = true, ui = true, remote = false) */
{ static getInstance (verbose = true, ui = true, remote = false)
this.verbose = verbose; {
this.ui = ui; if(!Logger.instance) {
this.remote = remote; Logger.instance = new Logger(verbose, ui, remote);
}; }
/** return Logger.instance;
* Get logging instance };
*
* @param {boolean} [verbose] Verbose logging /**
* @param {boolean} [ui] Ui logging * Interpolate message
* @param {boolean} [remote] Remote logging *
* * @param {string} message Message structure
* @return {Object} * @param {Object} [context] Context to put into message
* * @param {string} [level] Log level
* @since 1.0.0 *
*/ * @return {string}
static getInstance (verbose = true, ui = true, remote = false) *
{ * @since 1.0.0
if(!jsOMS.Log.Logger.instance) { */
jsOMS.Log.Logger.instance = new jsOMS.Log.Logger(verbose, ui, remote); 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 * Create context
* *
* @param {string} message Message structure * @param {string} message Message to display
* @param {Object} [context] Context to put into message * @param {Object} [context] Context to put into message
* @param {string} [level] Log level * @param {string} level Log level
* *
* @return {string} * @return {Object}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
interpolate (message, context, level) 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') { * Create log message
message = message.replace('{' + replace + '}', context[replace]); *
} * @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 * Create log message
* *
* @param {string} message Message to display * @param {string} message Message to display
* @param {Object} [context] Context to put into message * @param {Object} [context] Context to put into message
* @param {string} level Log level *
* * @return {void}
* @return {Object} *
* * @since 1.0.0
* @since 1.0.0 */
*/ critical (message, context = {})
createContext (message, context, level) {
{ this.write(message, context, LogLevel.CRITICAL);
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;
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 * Create log message
* *
* @param {string} message Message to display * @param {string} message Message to display
* @param {Object} [context] Context to put into message * @param {Object} [context] Context to put into message
* @param {string} level Log level *
* * @return {void}
* @return {void} *
* * @since 1.0.0
* @since 1.0.0 */
*/ warning (message, context = {})
write (message, context, level) {
{ this.write(message, context, LogLevel.WARNING);
context = this.createContext(message, context, level); };
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 * Create log message
* *
* @param {string} message Message to display * @param {string} level Log level
* @param {Object} [context] Context to put into message * @param {string} message Message to display
* @param {string} level Log level * @param {Object} [context] Context to put into message
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
writeVerbose (message, context, level) log (level, message, context = {})
{ {
let color = '000'; this.write(message, context, level);
};
switch (level) { /**
case 'info': * Create log message
case 'notice': *
case 'log': * @param {string} message Message to display
color = '000'; * @param {Object} [context] Context to put into message
break; *
case 'debug': * @return {void}
color = '289E39'; *
break; * @since 1.0.0
case 'warning': */
case 'alert': console (message, context = {})
color = 'FFA600'; {
break; this.writeVerbose(message, context, LogLevel.INFO);
case 'error': };
case 'critical': }
case 'emergency':
color = 'CF304A';
break;
default:
}
console.log('%c' + this.interpolate(message, context, level), 'color: #' + color); Logger.instance = null;
}; Logger.MSG_FULL = '{datetime}; {level}; {version}; {os}; {browser}; {path}; {message}';
/**
* 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 || {}));

View File

@ -6,66 +6,58 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class AppNotification {
{ /**
"use strict"; * @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 { /**
/** * Create notification
* @constructor *
* * @param {Object} msg Notification
* @since 1.0.0 *
*/ * @return {void}
constructor () *
* @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; document.getElementsByClassName('log-msg')[0].remove();
}; }, 3000);
};
/** };
* 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 || {}));

View File

@ -6,75 +6,67 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class BrowserNotification {
{ /**
"use strict"; * @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 { /**
/** * Ask for browser permission to create notifications
* @constructor *
* * @return {void}
* @since 1.0.0 *
*/ * @since 1.0.0
constructor() */
{ requestPermission ()
this.status = 0; {
}; const self = this;
/** /** global: Notification */
* Set notification status. if(Notification.permission !== 'granted' && Notification.permission !== 'denied') {
* Notification.requestPermission(function(permission) {
* @param {int} status Notification status if(permission === 'granted') {
* let msg = new jsOMS.Message.Notification.NotificationMessage();
* @return {void}
*
* @since 1.0.0
*/
setStatus (status)
{
this.status = status;
};
/** self.send(msg);
* Ask for browser permission to create notifications }
* });
* @return {void} }
* };
* @since 1.0.0
*/
requestPermission ()
{
const self = this;
/** global: Notification */ /**
if(Notification.permission !== 'granted' && Notification.permission !== 'denied') { * Create notification
Notification.requestPermission(function(permission) { *
if(permission === 'granted') { * @param {Object} msg Notification
let msg = new jsOMS.Message.Notification.NotificationMessage(); *
* @return {void}
self.send(msg); *
} * @since 1.0.0
}); */
} send (msg)
}; {
// todo: implement
/** /** global: Notification */
* Create notification let n = new 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 || {}));

View File

@ -6,16 +6,9 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) { export const NotificationLevel = Object.freeze({
"use strict"; OK: 'ok',
INFO: 'info',
/** @namespace jsOMS.Message.Notification */ WARNING: 'warning',
jsOMS.Autoloader.defineNamespace('jsOMS.Message.Notification'); ERROR: 'error'
});
jsOMS.Message.Notification.NotificationLevel = Object.freeze({
OK: 'ok',
INFO: 'info',
WARNING: 'warning',
ERROR: 'error'
});
}(window.jsOMS = window.jsOMS || {}));

View File

@ -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. * Notification manager.
* *
@ -6,66 +10,58 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class NotificationManager {
{ /**
"use strict"; * @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 { /**
/** * Get the app notification manager.
* @constructor *
* * @return {Object}
* @since 1.0.0 *
*/ * @since 1.0.0
constructor() */
{ getAppNotifier ()
this.appNotifier = new jsOMS.Message.Notification.App.AppNotification(); {
this.browserNotifier = new jsOMS.Message.Notification.Browser.BrowserNotification(); return this.appNotifier;
}; };
/** /**
* Create notification. * Get the browser notification manager.
* *
* @param {Object} message Message object * @return {Object}
* @param {int} type Notification type *
* * @since 1.0.0
* @return {void} */
* getBrowserNotifier ()
* @since 1.0.0 {
*/ return this.browserNotifier;
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 || {}));

View File

@ -6,27 +6,20 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) { export class NotificationMessage {
"use strict"; /**
* @constructor
/** @namespace jsOMS.Message.Notification.App */ *
jsOMS.Autoloader.defineNamespace('jsOMS.Message.Notification'); * @param {string} status Message status
* @param {string} title Message title
jsOMS.Message.Notification.NotificationMessage = class { * @param {string} message Message content
/** *
* @constructor * @since 1.0.0
* */
* @param {string} status Message status constructor(status, title, message)
* @param {string} title Message title {
* @param {string} message Message content this.status = status;
* this.title = title;
* @since 1.0.0 this.message = message;
*/ };
constructor(status, title, message) };
{
this.status = status;
this.title = title;
this.message = message;
};
}
}(window.jsOMS = window.jsOMS || {}));

View File

@ -6,15 +6,7 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const NotificationType = Object.freeze({
{ APP_NOTIFICATION: 1,
"use strict"; BROWSER_NOTIFICATION: 2
});
/** @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 || {}));

View File

@ -6,21 +6,13 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const BrowserType = Object.freeze({
{ OPERA: 'opera',
"use strict"; FIREFOX: 'firefox',
SAFARI: 'safari',
/** @namespace jsOMS.Message.Request */ IE: 'msie',
jsOMS.Autoloader.defineNamespace('jsOMS.Message.Request'); EDGE: 'edge',
CHROME: 'chrome',
jsOMS.Message.Request.BrowserType = Object.freeze({ BLINK: 'blink',
OPERA: 'opera', UNKNOWN: 'unknown'
FIREFOX: 'firefox', });
SAFARI: 'safari',
IE: 'msie',
EDGE: 'edge',
CHROME: 'chrome',
BLINK: 'blink',
UNKNOWN: 'unknown'
});
}(window.jsOMS = window.jsOMS || {}));

View File

@ -6,38 +6,30 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const OSType = Object.freeze({
{ WINDOWS_10: 'windows nt 10.0', /* Windows 10 */
"use strict"; WINDOWS_81: 'windows nt 6.3', /* Windows 8.1 */
WINDOWS_8: 'windows nt 6.2', /* Windows 8 */
/** @namespace jsOMS.Message.Request */ WINDOWS_7: 'windows nt 6.1', /* Windows 7 */
jsOMS.Autoloader.defineNamespace('jsOMS.Message.Request'); WINDOWS_VISTA: 'windows nt 6.0', /* Windows Vista */
WINDOWS_SERVER: 'windows nt 5.2', /* Windows Server 2003/XP x64 */
jsOMS.Message.Request.OSType = Object.freeze({ WINDOWS_XP: 'windows nt 5.1', /* Windows XP */
WINDOWS_10: 'windows nt 10.0', /* Windows 10 */ WINDOWS_XP_2: 'windows xp', /* Windows XP */
WINDOWS_81: 'windows nt 6.3', /* Windows 8.1 */ WINDOWS_2000: 'windows nt 5.0', /* Windows 2000 */
WINDOWS_8: 'windows nt 6.2', /* Windows 8 */ WINDOWS_ME: 'windows me', /* Windows ME */
WINDOWS_7: 'windows nt 6.1', /* Windows 7 */ WINDOWS_98: 'win98', /* Windows 98 */
WINDOWS_VISTA: 'windows nt 6.0', /* Windows Vista */ WINDOWS_95: 'win95', /* Windows 95 */
WINDOWS_SERVER: 'windows nt 5.2', /* Windows Server 2003/XP x64 */ WINDOWS_311: 'win16', /* Windows 3.11 */
WINDOWS_XP: 'windows nt 5.1', /* Windows XP */ MAC_OS_X: 'macintosh', /* Mac OS X */
WINDOWS_XP_2: 'windows xp', /* Windows XP */ MAC_OS_X_2: 'mac os x', /* Mac OS X */
WINDOWS_2000: 'windows nt 5.0', /* Windows 2000 */ MAC_OS_9: 'mac_powerpc', /* Mac OS 9 */
WINDOWS_ME: 'windows me', /* Windows ME */ LINUX : 'linux', /* Linux */
WINDOWS_98: 'win98', /* Windows 98 */ UBUNTU: 'ubuntu', /* Ubuntu */
WINDOWS_95: 'win95', /* Windows 95 */ IPHONE: 'iphone', /* IPhone */
WINDOWS_311: 'win16', /* Windows 3.11 */ IPOD: 'ipod', /* IPod */
MAC_OS_X: 'macintosh', /* Mac OS X */ IPAD: 'ipad', /* IPad */
MAC_OS_X_2: 'mac os x', /* Mac OS X */ ANDROID: 'android', /* Android */
MAC_OS_9: 'mac_powerpc', /* Mac OS 9 */ BLACKBERRY: 'blackberry', /* Blackberry */
LINUX : 'linux', /* Linux */ MOBILE: 'webos', /* Mobile */
UBUNTU: 'ubuntu', /* Ubuntu */ UNKNOWN: 'UNKNOWN' /* Unknown */
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 || {}));

View File

@ -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. * Request class.
* *
@ -6,382 +13,374 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class Request {
{ /**
"use strict"; * @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 */ this.requestHeader['Content-Type'] = this.setContentTypeBasedOnType(this.type);
jsOMS.Autoloader.defineNamespace('jsOMS.Message.Request');
jsOMS.Message.Request.Request = class { this.result[0] = function()
/**
* @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; Logger.instance.info('Unhandled response');
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();
}; };
/** /** global: XMLHttpRequest */
* Defines the request content type based on the type this.xhr = new XMLHttpRequest();
* };
* @return {string}
* /**
* @since 1.0.0 * Defines the request content type based on the type
*/ *
setContentTypeBasedOnType(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) { switch (self.xhr.readyState) {
case jsOMS.Message.Request.RequestType.JSON: case 4:
return 'application/json'; if (typeof self.result[self.xhr.status] === 'undefined') {
case jsOMS.Message.Request.RequestType.URL_ENCODE: self.result[0](self.xhr);
return 'application/x-www-form-urlencoded'; } else {
case jsOMS.Message.Request.RequestType.FILE: self.result[self.xhr.status](self.xhr);
return ''; }
break;
default: default:
return 'text/plain';
} }
}; };
/** if (this.type === RequestType.JSON) {
* Get browser. this.xhr.send(JSON.stringify(this.data));
* } else if (this.type === RequestType.RAW
* @return {string} || this.type === RequestType.FILE
* ) {
* @since 1.0.0 this.xhr.send(this.data);
*/ } else if (this.type === RequestType.URL_ENCODE) {
static getBrowser() this.xhr.send(this.queryfy(this.data));
{ }
/** 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 || {}));

View File

@ -6,18 +6,10 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const RequestMethod = Object.freeze({
{ POST: 'POST',
"use strict"; GET: 'GET',
PUT: 'PUT',
/** @namespace jsOMS.Message.Request */ DELETE: 'DELETE',
jsOMS.Autoloader.defineNamespace('jsOMS.Message.Request'); HEAD: 'HEAD'
});
jsOMS.Message.Request.RequestMethod = Object.freeze({
POST: 'POST',
GET: 'GET',
PUT: 'PUT',
DELETE: 'DELETE',
HEAD: 'HEAD'
});
}(window.jsOMS = window.jsOMS || {}));

View File

@ -6,17 +6,9 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const RequestType = Object.freeze({
{ JSON: 'json',
"use strict"; RAW: 'raw',
FILE: 'file',
/** @namespace jsOMS.Message.Request */ URL_ENCODE: 'url'
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 || {}));

View File

@ -8,50 +8,42 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class Response {
{ /**
"use strict"; * @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 { /**
/** * Count the amount of responses.
* @constructor *
* * @return {int}
* @param {mixed} data Response data *
* * @since 1.0.0
* @since 1.0.0 */
*/ count ()
constructor (data) {
{ return this.responses.length;
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 || {}));

View File

@ -8,69 +8,61 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class ResponseManager {
{ /**
"use strict"; * @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 { this.messages[key][request] = message;
/** };
* @constructor
*
* @since 1.0.0
*/
constructor()
{
this.messages = {};
};
/** /**
* Add response handler. * Execute a predefined callback.
* *
* This allows the response handler to generally handle responses and also handle specific requests if defined. * Tries to execute a request specific callback or otherwise a general callback if defined.
* *
* @param {string} key Response key * @param {string} key Response key
* @param {requestCallback} message Callback for message * @param {Array|Object} data Date to use in callback
* @param {string} [request] Request id in order to only handle a specific request * @param {jsOMS.Message.Request.Request} [request] Request id for request specific execution
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
add(key, message, request) run(key, data, request)
{ {
request = typeof request !== 'undefined' ? request : 'any'; if (typeof request !== 'undefined' && typeof this.messages[key] !== 'undefined' && typeof this.messages[key][request] !== 'undefined') {
if (typeof this.messages[key] === 'undefined') { this.messages[key][request](data);
this.messages[key] = []; } else if (typeof this.messages[key] !== 'undefined') {
} this.messages[key].any(data);
} else {
this.messages[key][request] = message; jsOMS.Log.Logger.instance.warning('Undefined type: ' + key);
}; }
};
/** };
* 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 || {}));

View File

@ -6,19 +6,11 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const ResponseType = Object.freeze({
{ TEXT: 'text',
"use strict"; JSON: 'json',
DOCUMENT: 'document',
/** @namespace jsOMS.Message.Response */ BLOB: 'blob',
jsOMS.Autoloader.defineNamespace('jsOMS.Message.Response'); ARRAYBUFFER: 'arraybuffer',
DEFAULT: ''
jsOMS.Message.Response.ResponseType = Object.freeze({ });
TEXT: 'text',
JSON: 'json',
DOCUMENT: 'document',
BLOB: 'blob',
ARRAYBUFFER: 'arraybuffer',
DEFAULT: ''
});
}(window.jsOMS = window.jsOMS || {}));

View File

@ -6,7 +6,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const datalistAppend = function (action, callback) export function datalistAppend (action, callback)
{ {
"use strict"; "use strict";

View File

@ -6,7 +6,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const datalistClear = function (action, callback) export function datalistClear (action, callback)
{ {
"use strict"; "use strict";

View File

@ -1,4 +1,4 @@
const focusAction = function (action, callback) export function focusAction (action, callback)
{ {
"use strict"; "use strict";

View File

@ -7,7 +7,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const domGetValue = function (action, callback, id) export function domGetValue (action, callback, id)
{ {
"use strict"; "use strict";

View File

@ -1,4 +1,4 @@
const hideAction = function (action, callback) export function hideAction (action, callback)
{ {
"use strict"; "use strict";

View File

@ -7,7 +7,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const popupButtonAction = function (action, callback, id) export function popupButtonAction (action, callback, id)
{ {
"use strict"; "use strict";

View File

@ -7,7 +7,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const removeButtonAction = function (action, callback, id) export function removeButtonAction (action, callback, id)
{ {
"use strict"; "use strict";

View File

@ -7,7 +7,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const domRemoveValue = function (action, callback, id) export function domRemoveValue (action, callback, id)
{ {
"use strict"; "use strict";

View File

@ -7,7 +7,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const domSetValue = function (action, callback, id) export function domSetValue (action, callback, id)
{ {
"use strict"; "use strict";

View File

@ -1,4 +1,4 @@
const showAction = function (action, callback) export function showAction (action, callback)
{ {
"use strict"; "use strict";

View File

@ -6,7 +6,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const tableAppend = function (action, callback) export function tableAppend (action, callback)
{ {
"use strict"; "use strict";

View File

@ -6,7 +6,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const tableClear = function (action, callback) export function tableClear (action, callback)
{ {
"use strict"; "use strict";

View File

@ -7,7 +7,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const preventEvent = function (action, callback, id) export function preventEvent (action, callback, id)
{ {
"use strict"; "use strict";

View File

@ -6,7 +6,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const logAction = function (action, callback) export function logAction (action, callback)
{ {
"use strict"; "use strict";

View File

@ -6,7 +6,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const requestAction = function (action, callback) export function requestAction (action, callback)
{ {
"use strict"; "use strict";

View File

@ -6,7 +6,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const dataCollectionAction = function (action, callback) export function dataCollectionAction (action, callback)
{ {
"use strict"; "use strict";

View File

@ -7,7 +7,7 @@
* @since 1.0.0 * @since 1.0.0
*/ */
const timerActionDelay = {}; const timerActionDelay = {};
const timerAction = function (action, callback, data) export function timerAction (action, callback, data)
{ {
"use strict"; "use strict";

View File

@ -6,7 +6,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const validateKeypress = function (action, callback) export function validateKeypress (action, callback)
{ {
"use strict"; "use strict";

View File

@ -5,7 +5,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const domAction = function (data) export function domAction (data)
{ {
/** global: jsOMS */ /** global: jsOMS */
setTimeout(function () setTimeout(function ()

View File

@ -1,15 +1,11 @@
(function (jsOMS) { export const EnumDomActionType = Object.freeze({
"use strict"; CREATE_BEFORE: 0,
CREATE_AFTER: 1,
jsOMS.EnumDomActionType = Object.freeze({ DELETE: 2,
CREATE_BEFORE: 0, REPLACE: 3,
CREATE_AFTER: 1, MODIFY: 4,
DELETE: 2, SHOW: 5,
REPLACE: 3, HIDE: 6,
MODIFY: 4, ACTIVATE: 7,
SHOW: 5, DEACTIVATE: 8
HIDE: 6, });
ACTIVATE: 7,
DEACTIVATE: 8
});
} (window.jsOMS = window.jsOMS || {}));

View File

@ -5,7 +5,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const formValidationMessage = function (data) { export function formValidationMessage (data) {
const form = document.getElementById(data.form); const form = document.getElementById(data.form);
if(!form) { if(!form) {

View File

@ -5,7 +5,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const notifyMessage = function (data) export function notifyMessage (data)
{ {
setTimeout(function () setTimeout(function ()
{ {

View File

@ -1,11 +1,8 @@
(function (jsOMS) { export const EnumNotifyType = Object.freeze({
"use strict"; 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 || {}));

View File

@ -1,3 +1,5 @@
import { UriFactory } from '../../Uri/UriFactory.js';
/** /**
* Set message. * Set message.
* *
@ -5,11 +7,11 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const redirectMessage = function (data) export function redirectMessage (data)
{ {
setTimeout(function () setTimeout(function ()
{ {
/** global: jsOMS */ /** global: jsOMS */
window.location = jsOMS.Uri.UriFactory.build(data.uri); window.location = UriFactory.build(data.uri);
}, parseInt(data.delay)); }, parseInt(data.delay));
}; };

View File

@ -5,7 +5,7 @@
* *
* @since 1.0.0 * @since 1.0.0
*/ */
const reloadMessage = function (data) { export function reloadMessage (data) {
setTimeout(function () { setTimeout(function () {
document.location.reload(true); document.location.reload(true);
}, parseInt(data.delay)); }, parseInt(data.delay));

View File

@ -6,35 +6,28 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class ModuleFactory {
{ /**
"use strict"; * @constructor
*
* @since 1.0.0
*/
constructor ()
{
};
jsOMS.Autoloader.defineNamespace('jsOMS.Module'); /**
* Get module instance.
jsOMS.Module.ModuleFactory = class { *
/** * @param {string} module Module name
* @constructor * @param {Object} app Application reference
* *
* @since 1.0.0 * @return {Object}
*/ *
constructor () * @since 1.0.0
{ */
}; static getInstance (module, app)
{
/** return new jsOMS.Modules[module](app);
* 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 || {}));

View File

@ -1,3 +1,4 @@
import { ModuleFactory } from './ModuleFactory.js';
/** /**
* Module manager. * Module manager.
* *
@ -6,43 +7,35 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class ModuleManager {
{ /**
"use strict"; * @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 { return this.modules[module];
/** };
* @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 || {}));

View File

@ -6,192 +6,184 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class ActionManager {
{ /**
"use strict"; * @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 { for (let i = 0; i < length; ++i) {
/** if (uiElements[i] !== null && uiElements[i].hasAttribute('data-action')) {
* @constructor this.bindElement(uiElements[i]);
*
* @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]);
}
} }
}; }
};
/** /**
* Bind element. * Bind element.
* *
* @param {Element} e Element to bind * @param {Element} e Element to bind
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
bindElement (e) bindElement (e)
{ {
if (!jsOMS.isValidJson(e.getAttribute('data-action'))) { if (!jsOMS.isValidJson(e.getAttribute('data-action'))) {
jsOMS.Log.Logger.instance.error('Invalid json string: \'' + 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; return;
} }
// todo: validate json, if invalid log error this.app.eventManager.attach(id + '-' + listener.key + '-' + listener.action[j - 1].key, function (data)
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)
{ {
if (listener.preventDefault) { self.runAction(id, listener, listener.action[j], data);
jsOMS.preventAll(event); }, 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); // Register event for first action
}); document.getElementById(id).addEventListener(listener.listener, function (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)
{ {
const self = this; if (listener.preventDefault) {
jsOMS.preventAll(event);
if (!this.actions.hasOwnProperty(action.type)) {
jsOMS.Log.Logger.instance.warning('Undefined action ' + action.type);
return;
} }
action.data = data; self.runAction(this.id, listener, listener.action[0], event);
});
};
this.actions[action.type](action, function (data) /**
{ * Run event action.
self.app.eventManager.trigger(id + '-' + listener.key + '-' + action.key, id, data); *
}, id); * @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;
/** if (!this.actions.hasOwnProperty(action.type)) {
* Add action callback. jsOMS.Log.Logger.instance.warning('Undefined action ' + action.type);
* return;
* @param {string} name Action identifier }
* @param {function} callback Action callback
* action.data = data;
* @return {void}
* this.actions[action.type](action, function (data)
* @since 1.0.0
*/
add (name, callback)
{ {
this.actions[name] = callback; self.app.eventManager.trigger(id + '-' + listener.key + '-' + action.key, id, data);
}; }, id);
} };
}(window.jsOMS = window.jsOMS || {}));
/**
* 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;
};
};

View File

@ -1,3 +1,4 @@
import { Request } from '../../Message/Request/Request.js';
/** /**
* Advanced input class. * 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: 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. * @todo: Passing self to every MEMBER function is just dumb.
*/ */
(function (jsOMS) export class AdvancedInput {
{ /**
"use strict"; * @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 */ const self = this;
jsOMS.Autoloader.defineNamespace('jsOMS.UI.Component'); this.inputField.addEventListener('focusout', function(e) {
// todo: this also means that clicking on any other part of the result list that it disappears befor
jsOMS.UI.Component.AdvancedInput = class { // 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
* @constructor // first then I could simply say, don't make the result div inactive!
* if (e.relatedTarget === null ||
* @param {object} e Element to bind e.relatedTarget.parentElement === null ||
* e.relatedTarget.parentElement.parentElement === null ||
* @since 1.0.0 !jsOMS.hasClass(e.relatedTarget.parentElement.parentElement.parentElement, 'dropdown')
*/ ) {
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);
jsOMS.removeClass(self.dropdownElement, 'active'); jsOMS.removeClass(self.dropdownElement, 'active');
}); }
});
this.dropdownElement.addEventListener('click', function(e) { this.inputField.addEventListener('keydown', function(e) {
if (document.activeElement.tagName.toLowerCase() !== 'tr') { if (e.keyCode === 13 || e.keyCode === 40) {
return; 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.clearDataListSelection(self);
self.addToResultList(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);
});
}
} }
}; });
/** this.dropdownElement.addEventListener('focusout', function(e) {
* Callback for input field content change self.clearDataListSelection(self);
* jsOMS.removeClass(self.dropdownElement, 'active');
* @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('click', function(e) {
* Select element in dropdown (only mark it as selected) if (document.activeElement.tagName.toLowerCase() !== 'tr') {
* return;
* @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') { self.clearDataListSelection(self);
// todo: make badges removable self.addToResultList(self);
const newTag = self.tagTpl.content.cloneNode(true); 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 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) { for (let j = 0; j < fieldLength; ++j) {
fields[j].appendChild( fields[j].appendChild(
document.createTextNode( 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 // set internal value
if (self.tagElement.childElementCount >= self.tagElement.getAttribute('data-limit') fields = newRow.querySelectorAll('[data-tpl-value]');
&& self.tagElement.getAttribute('data-limit') != 0 fieldLength = fields.length;
) {
self.tagElement.removeChild(self.tagElement.firstElementChild); 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') { // don't allow duplicate
self.inputField.value = ''; if (self.tagElement.querySelectorAll('[data-tpl-uuid="' + uuid + '"').length !== 0) {
return;
} }
self.inputField.focus(); newTag.firstElementChild.setAttribute('data-tpl-uuid', uuid);
};
/** // set readable text
* Delay handler (e.g. delay after finishing typing) fields = newTag.querySelectorAll('[data-tpl-text]');
* fieldLength = fields.length;
* After waiting for a delay a callback can be triggered.
* for (let j = 0; j < fieldLength; ++j) {
* @param {object} action Action type fields[j].appendChild(
* @param {function} callback Callback to be triggered document.createTextNode(
* @param {object} self This reference (passed to callback) document.activeElement.querySelectorAll('[data-tpl-text="' + fields[j].getAttribute('data-tpl-text') + '"]')[0].innerText
* @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]
} }
jsOMS.UI.Component.AdvancedInput.timerDelay[action.id] = setTimeout(function() { // allow limit
delete jsOMS.UI.Component.AdvancedInput.timerDelay[action.id]; if (self.tagElement.childElementCount >= self.tagElement.getAttribute('data-limit')
callback(self, data); && self.tagElement.getAttribute('data-limit') != 0
}, action.delay); ) {
}; self.tagElement.removeChild(self.tagElement.firstElementChild);
} }
jsOMS.UI.Component.AdvancedInput.timerDelay = {}; self.tagElement.appendChild(newTag);
}(window.jsOMS = window.jsOMS || {})); }
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 = {};

View File

@ -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. * Form manager class.
* *
@ -6,301 +13,293 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class Form {
{ /**
"use strict"; * @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 { return this.forms[id];
/** };
* @constructor
*
* @param {Object} app Application
*
* @since 1.0.0
*/
constructor (app)
{
this.app = app;
this.forms = {};
this.ignore = {};
};
/** /**
* Get form * Is form ignored?
* *
* @param {string} id Form Id * @param {string} id Form Id
* *
* @return {void} * @return {boolean}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
get (id) isIgnored (id)
{ {
if (!this.forms.hasOwnProperty(id)) { return this.ignore.indexOf(id) !== -1;
this.bind(id); };
}
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 * Bind form
* *
* @param {string} id Form Id * @param {string} id Form Id (optional)
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
unbind (id) bind (id)
{ {
if (typeof id !== 'undefined' && typeof this.ignore[id] === 'undefined') {
}; this.bindForm(id);
} else {
/** const forms = document.getElementsByTagName('form'),
* Bind form length = !forms ? 0 : forms.length;
*
* @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;
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
submits[i].addEventListener('click', function (event) let formId = forms[i].getAttribute('id');
{ if (typeof formId !== 'undefined' && formId !== null && typeof this.ignore[formId] === 'undefined') {
jsOMS.preventAll(event); this.bindForm(formId);
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.');
} }
} }
}
};
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;
}
/** const self = this;
* Submit form data this.forms[id] = new FormView(id);
*
* 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
);
jsOMS.Log.Logger.instance.debug('Form "' + form.getId() + '" has invalid values.'); this.unbind(id);
return;
}
if (form.getMethod() !== jsOMS.Message.Request.RequestMethod.GET const submits = this.forms[id].getSubmit(),
&& Math.abs(Date.now() - form.getLastSubmit()) < 500 length = submits.length;
) {
return;
}
form.updateLastSubmit(); for (let i = 0; i < length; ++i) {
submits[i].addEventListener('click', function (event)
/* 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)
{ {
console.log(xhr.response); jsOMS.preventAll(event);
self.submit(self.forms[id]);
});
}
};
try { /**
const o = JSON.parse(xhr.response), * Unbind form
response = new jsOMS.Message.Response.Response(o); *
let successInject = null; * @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) { if ((findex = this.forms[id]) !== 'undefined') {
successInject(response); this.forms[id].unbind();
} else if (typeof response.get(0) !== 'undefined' && typeof response.get(0).type !== 'undefined') { this.forms.splice(findex, 1);
// 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);
jsOMS.Log.Logger.instance.error('Invalid form response. \n' return true;
+ 'URL: ' + form.getAction() + '\n' }
+ 'Request: ' + JSON.stringify(form.getData()) + '\n'
+ 'Response: ' + xhr.response 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) Logger.instance.error('Invalid form response. \n'
{ + 'URL: ' + form.getAction() + '\n'
self.app.notifyManager.send( + 'Request: ' + JSON.stringify(form.getData()) + '\n'
new jsOMS.Message.Notification.NotificationMessage( + 'Response: ' + xhr.response
jsOMS.Message.Notification.NotificationLevel.ERROR,
'Failure',
'Some failure happend'
), jsOMS.Message.Notification.NotificationType.APP_NOTIFICATION
); );
});
request.send();
if (form.getFinally() !== null) {
form.getFinally()();
} }
}; });
/** request.setResultCallback(0, function (xhr)
* Count the bound forms
*
* @return {int}
*
* @since 1.0.0
*/
count ()
{ {
return this.forms.length; self.app.notifyManager.send(
}; new NotificationMessage(
} NotificationLevel.ERROR,
}(window.jsOMS = window.jsOMS || {})); '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;
};
};

View File

@ -6,174 +6,166 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class Input {
{ /**
"use strict"; * @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 { /**
/** * Bind input element
* @constructor *
* * @param {Object} input Input element
* @since 1.0.0 *
*/ * @return {void}
constructor () *
* @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; 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') {
* Unbind input element self.addRemoteDatalistOptions(this, list);
*
* @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'
} }
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'); const db = document.getElementById(dataButton);
/* 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);
}
/* Handle html defined functions */ if (db) {
let change; db.click();
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:
}
} }
}); });
}
};
let dataButton; /**
if (typeof (dataButton = input.getAttribute('data-button')) !== 'undefined') { * Add remote datalist options
this.app.inputManager.getKeyboardManager().bind(input, 13, function () *
{ * This only applies for datalists that have remote options
const db = document.getElementById(dataButton); *
* @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) { const request = new Request();
db.click(); 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)
/**
* 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); 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(); for (let k = 0; k < responseLength; ++k) {
request.setData(input.value); tempResponse = response.getByIndex(k);
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) { let option = null,
tempResponse = response.getByIndex(k); data = tempResponse.getData(),
length = data.length;
let option = null, for (let i = 0; i < length; ++i) {
data = tempResponse.getData(), option = document.createElement('option');
length = data.length; option.value = tempResponse.value;
option.text = tempResponse.text;
for (let i = 0; i < length; ++i) { datalist.appendChild(option);
option = document.createElement('option');
option.value = tempResponse.value;
option.text = tempResponse.text;
datalist.appendChild(option);
}
} }
} catch (exception) {
jsOMS.Log.Logger.instance.error('Invalid JSON object: ' + xhr, 'FormManager');
} }
}); } catch (exception) {
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);
} }
}; });
}
}(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);
}
};
};

View File

@ -1,3 +1,6 @@
import { UriFactory } from '../../Uri/UriFactory.js';
import { Http } from '../../Uri/Http.js';
/** /**
* Tab manager class. * Tab manager class.
* *
@ -6,133 +9,126 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class Tab {
{ /**
"use strict"; * @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 { if (e) {
/** this.bindElement(e);
* @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]);
}
} }
}; } else {
const tabs = document.getElementsByClassName('tabview'),
/** length = !tabs ? 0 : tabs.length;
* 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;
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
nodes[i].addEventListener('click', function (evt) this.bindElement(tabs[i]);
{ }
let fragmentString = window.location.href.includes('#') ? jsOMS.Uri.Http.parseUrl(window.location.href).fragment : ''; }
};
/* Change Tab */ /**
/* Remove selected tab */ * Bind & rebind UI element.
const oldActive = this.parentNode.getElementsByClassName('active'); *
if (oldActive.length > 0) { * @param {Object} e Element
// find old active and remove it *
fragmentString = jsOMS.trim( * @return {void}
fragmentString.replace(oldActive[0].getElementsByTagName('label')[0].getAttribute('for'), ''), *
',' * @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? /* Change Tab */
// todo: here is a bug or in the uri factory. replace also replaces substrings e.g. #test-c-tab-1 gets partially replaced /* Remove selected tab */
// 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 `#` const oldActive = this.parentNode.getElementsByClassName('active');
if (oldActive.length > 0) {
// find old active and remove it
fragmentString = jsOMS.trim( 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 */ // remove new element if new element already inside, alternatively check for existence and don't do a new push state?
window.history.pushState(null, '', // todo: here is a bug or in the uri factory. replace also replaces substrings e.g. #test-c-tab-1 gets partially replaced
jsOMS.Uri.UriFactory.build( // 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 === '' ? '' : fragmentString + ',') + this.getElementsByTagName('label')[0].getAttribute('for') fragmentString = jsOMS.trim(
) fragmentString.replace(this.getElementsByTagName('label')[0].getAttribute('for'), ''),
); ','
}); );
}
this.activateTabUri(e); jsOMS.addClass(this, 'active');
};
/** /* Add selected tab */
* Activates the correct tab based on URI fragment. window.history.pushState(null, '',
* UriFactory.build(
* This allows to link a specific open tab to a user or make it a bookmark '{%}#' + (fragmentString === '' ? '' : fragmentString + ',') + this.getElementsByTagName('label')[0].getAttribute('for')
* )
* @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;
if (fragLength > 0 && fragmentString !== '') { this.activateTabUri(e);
for (let i = 0; i < fragLength; ++i) { };
let label = e.querySelectorAll('label[for="' + fragments[i] + '"]')[0];
if (typeof label !== 'undefined') { /**
label.click(); * 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) { if (e.getElementsByClassName('active').length < 1) {
e.querySelector('label').click(); e.querySelector('label').click();
} }
}; };
} };
}(window.jsOMS = window.jsOMS || {}));

File diff suppressed because it is too large Load Diff

View File

@ -6,129 +6,121 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class DragNDrop {
{ /**
"use strict"; * @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 { /**
/** * Bind element
* @constructor *
* * @param {Object} id DOM element
* @since 1.0.0 *
*/ * @return {void}
constructor (app) *
{ * @since 1.0.0
this.app = app; */
this.draggable = {}; bind (id)
this.dragging = null; {
}; 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) {
* Unbind element if (typeof elements[i].getAttribute('id') !== 'undefined' && elements[i].getAttribute('id') !== null) {
* this.bindElement(elements[i].getAttribute('id'));
* @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'));
}
} }
} }
}; }
};
/** /**
* Bind DOM elment * Bind DOM elment
* *
* @param {string} id DOM element * @param {string} id DOM element
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
bindElement (id) bindElement (id)
{ {
const element = document.getElementById(id), const element = document.getElementById(id),
self = this; 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; return;
} }
element.addEventListener('dragstart', function(e) { self.dragging.innerHTML = this.innerHTML;
if (self.dragging === null) { this.innerHTML = e.dataTransfer.getData('text/html');
self.dragging = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
}
}, false);
element.addEventListener('dragenter', function(e) { // todo: add to now destination
// todo: highlight // todo: remove from old destination
}, false);
element.addEventListener('dragover', function(e) { self.dragging = null;
e.preventDefault(); }, false);
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);
}
} }
}(window.jsOMS = window.jsOMS || {})); };

View File

@ -1,3 +1,7 @@
import { AdvancedInput } from './Component/AdvancedInput.js';
import { UriFactory } from '../Uri/UriFactory.js';
/** /**
* UI manager for handling basic ui elements. * UI manager for handling basic ui elements.
* *
@ -6,121 +10,113 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class GeneralUI {
{ /**
"use strict"; * @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 { this.bindHref(e);
/** this.bindLazyLoad(e);
* @constructor this.bindInput(e);
* };
* @since 1.0.0
*/
constructor ()
{
this.visObs = null;
};
/** /**
* Bind button. * Bind & rebind UI element.
* *
* @param {string} [id] Button id (optional) * @param {Object} [e] Element id
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
bind (id) bindHref (e)
{ {
let e = null; e = e !== null ? e.querySelectorAll('[data-href]') : document.querySelectorAll('[data-href]');
if (typeof id !== 'undefined' && id !== null) { const length = e.length;
e = document.getElementById(id);
}
this.bindHref(e); for (let i = 0; i < length; ++i) {
this.bindLazyLoad(e); e[i].addEventListener('click', function(event) {
this.bindInput(e); jsOMS.preventAll(event);
}; window.location = UriFactory.build(this.getAttribute('data-href'));
});
}
};
/** /**
* Bind & rebind UI element. * Bind & rebind UI element.
* *
* @param {Object} [e] Element id * @param {Object} [e] Element id
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
bindHref (e) bindLazyLoad (e)
{ {
e = e !== null ? e.querySelectorAll('[data-href]') : document.querySelectorAll('[data-href]'); e = e !== null ? e.querySelectorAll('[data-lazyload]') : document.querySelectorAll('[data-lazyload]');
const length = e.length; const length = e.length;
for (let i = 0; i < length; ++i) { /** global: IntersectionObserver */
e[i].addEventListener('click', function(event) { if (!this.visObs && window.IntersectionObserver) {
jsOMS.preventAll(event); this.visObs = new IntersectionObserver(function(eles, obs) {
window.location = jsOMS.Uri.UriFactory.build(this.getAttribute('data-href')); 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. * Bind & rebind UI element.
* *
* @param {Object} [e] Element id * @param {Object} [e] Element id
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
bindLazyLoad (e) bindInput (e)
{ {
e = e !== null ? e.querySelectorAll('[data-lazyload]') : document.querySelectorAll('[data-lazyload]'); e = e !== null ? [e] : document.getElementsByClassName('advancedInput');
const length = e.length; const length = e.length;
/** global: IntersectionObserver */ for (let i = 0; i < length; ++i) {
if (!this.visObs && window.IntersectionObserver) { new AdvancedInput(e[i]);
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 || {}));

View File

@ -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. * UI manager class.
* *
@ -6,60 +10,52 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class InputManager {
{ /**
"use strict"; * @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 { /**
/** * Get mouse manager.
* @constructor *
* * @return {Object}
* @since 1.0.0 *
*/ * @since 1.0.0
constructor(app) */
{ getMouseManager ()
this.keyboardManager = new jsOMS.UI.Input.Keyboard.KeyboardManager(); {
this.mouseManager = new jsOMS.UI.Input.Mouse.MouseManager(); return this.mouseManager;
this.voiceManager = new jsOMS.UI.Input.Voice.VoiceManager(app); };
};
/** /**
* Get keyboard manager. * Get voice manager.
* *
* @return {Object} * @return {Object}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getKeyboardManager () getVoiceManager ()
{ {
return this.keyboardManager; return this.voiceManager;
}; };
};
/**
* 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 || {}));

View File

@ -6,116 +6,108 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class KeyboardManager {
{ /**
"use strict"; * @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 { this.bind(element);
/** }
* @constructor
* this.elements[element].push({keys: keys, callback: callback});
* @since 1.0.0 };
*/
constructor () /**
* 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 = {}; self.down.push(event.keyCode);
this.down = []; });
};
/** document.addEventListener('keyup', function keyBind(event)
* 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') { if (self.down.length > 0) {
this.elements[element] = []; self.run(element, event);
self.down = [];
this.bind(element);
} }
});
};
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!';
}
/** const actions = this.elements[element],
* Bind container for keyboard input. length = actions.length,
* keyLength = this.down.length;
* @param {string} element Container id let match = false;
*
* @return {void}
*
* @since 1.0.0
*/
bind (element)
{
const self = this;
// todo: implement keyboard for selected elements right now only global hotkeys possible for (let i = 0; i < length; ++i) {
document.addEventListener('keydown', function keyBind(event) for (let j = 0; j < keyLength; ++j) {
{ if (actions[i].keys.indexOf(this.down[j]) === -1) {
self.down.push(event.keyCode); match = false;
});
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();
break; break;
} }
match = true;
} }
};
} if (match) {
}(window.jsOMS = window.jsOMS || {})); jsOMS.preventAll(event);
actions[i].callback();
break;
}
}
};
};

View File

@ -6,16 +6,8 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const ClickType = Object.freeze({
{ LEFT: 0,
"use strict"; MIDDLE: 1,
RIGHT: 2
/** @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 || {}));

View File

@ -6,16 +6,8 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export const EventType = Object.freeze({
{ CONTEXT: 0,
"use strict"; LONGPRESS: 1,
CLICK: 2
/** @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 || {}));

View File

@ -1,3 +1,5 @@
import { EventType } from '../../../../jsOMS/UI/Input/Mouse/EventType.js';
/** /**
* Mouse manager class. * Mouse manager class.
* *
@ -6,123 +8,115 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class MouseManager {
{ /**
"use strict"; * @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 { this.bind(element, type);
/** this.elements[element].push({callback: callback, type: type, button: button, exact: exact});
* @constructor };
*
* @since 1.0.0
*/
constructor ()
{
this.elements = {};
this.click = {time: 0};
};
/** /**
* Add input listener. * Add input listener.
* *
* @param {string} element Container id * @param {string} element Element id
* @param {int} type Action type * @param {int} type Action type
* @param {int} button Button *
* @param {callback} callback Callback * @return {void}
* @param {bool} exact ??? todo: can't remember why this was important oO!!! *
* * @since 1.0.0
* @return {void} */
* bind (element, type)
* @since 1.0.0 {
*/ const self = this,
add (element, type, button, callback, exact) e = document.getElementById(element);
{
if (typeof this.elements[element] === 'undefined') {
this.elements[element] = [];
}
this.bind(element, type); if (!e) {
this.elements[element].push({callback: callback, type: type, button: button, exact: exact}); return;
}; }
/** if (type === EventType.CONTEXT) {
* Add input listener. e.addEventListener('contextmenu', function (event)
* {
* @param {string} element Element id self.run(element, event);
* @param {int} type Action type }, false);
* } else if (type === EventType.LONGPRESS) {
* @return {void} e.addEventListener('mousedown', function (event)
* {
* @since 1.0.0 self.click.time = new Date().getTime();
*/ }, false);
bind (element, type)
{
const self = this,
e = document.getElementById(element);
if (!e) { e.addEventListener('mouseup', function (event)
return; {
} const duration = new Date().getTime() - self.click.time;
if (type === jsOMS.UI.Input.Mouse.EventType.CONTEXT) { if (duration > 650) {
e.addEventListener('contextmenu', function (event)
{
self.run(element, event); 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 || {})); };

View File

@ -6,126 +6,118 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class TouchManager {
{ /**
"use strict"; * @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 { /**
/** * Adding swipe functionality.
* @constructor *
* * Forwarding swipe to arrow keys.
* @param {Object} app Application *
* * @return {void}
* @since 1.0.0 *
*/ * @since 1.0.0
constructor (app) */
add (surface)
{
const e = document.getElementById(surface),
self = this;
if (!e) {
return;
}
e.addEventListener('touchstart', function (event)
{ {
this.app = app; const touch = this.changedTouches[0];
this.activeSwipe = {};
this.resetSwipe();
};
/** self.activeSwipe.startX = touch.pageX;
* Reset swipe data. self.activeSwipe.startY = touch.pageY;
* self.activeSwipe.time = new Date().getTime();
* This is called in between swipes in order to reset previous swipe data.
* jsOMS.preventAll(event);
* @return {void} });
*
* @since 1.0.0 e.addEventListener('touchmove', function (event)
*/
resetSwipe ()
{ {
this.activeSwipe = {'startX': null, 'startY': null, 'time': null}; jsOMS.preventAll(event);
}; });
/** e.addEventListener('touchend', function (event)
* Adding swipe functionality.
*
* Forwarding swipe to arrow keys.
*
* @return {void}
*
* @since 1.0.0
*/
add (surface)
{ {
const e = document.getElementById(surface), const touch = this.changedTouches[0],
self = this; distX = touch.pageX - self.activeSwipe.startX,
distY = touch.pageY - self.activeSwipe.startY,
elapsedTime = new Date().getTime() - self.activeSwipe.time;
if (!e) { self.resetSwipe();
return; // todo: only prevent all if success
} jsOMS.preventAll(event);
e.addEventListener('touchstart', function (event) if (elapsedTime > 300 && distY < 3 && distX < 3) {
{ let rightClick = MouseEvent('click',
const touch = this.changedTouches[0]; {
bubbles: true,
self.activeSwipe.startX = touch.pageX; cancelable: true,
self.activeSwipe.startY = touch.pageY; view: window,
self.activeSwipe.time = new Date().getTime(); screenX: touch.pageX,
screenY: touch.pageY,
jsOMS.preventAll(event); clientX: touch.pageX,
}); clientY: touch.pageY,
ctrlKey: false,
e.addEventListener('touchmove', function (event) altKey: false,
{ shiftKey: false,
jsOMS.preventAll(event); metaKey: false,
}); button: 2,
relatedTarget: null
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);
} }
);
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 || {})); };

View File

@ -6,121 +6,113 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class ReadManager {
{ /**
"use strict"; * @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 */ if (SpeechRecognition !== null) {
jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input.Voice'); this.voices = window.speechSynthesis.getVoices();
this.voice = this.voices[0];
}
};
// todo: remove once obsolete /**
/** global: webkitSpeechRecognition */ * Read text.
/** global: SpeechRecognition */ *
var SpeechRecognition = typeof SpeechRecognition !== 'undefined' ? SpeechRecognition : typeof webkitSpeechRecognition !== 'undefined' ? webkitSpeechRecognition : null; * @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 */ window.speechSynthesis.speak(utter);
/** global: SpeechGrammarList */ };
var SpeechGrammarList = typeof SpeechGrammarList !== 'undefined' ? SpeechGrammarList : typeof webkitSpeechGrammarList !== 'undefined' ? webkitSpeechGrammarList : null;
/** global: webkitSpeechRecognitionEvent */ /**
/** global: SpeechRecognitionEvent */ * Set Language.
var SpeechRecognitionEvent = typeof SpeechRecognitionEvent !== 'undefined' ? SpeechRecognitionEvent : typeof webkitSpeechRecognitionEvent !== 'undefined' ? webkitSpeechRecognitionEvent : null; *
* @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 { /**
/** * Set pitch.
* @constructor *
* * @param {int} pitch Pitch
* @param {string} lang Localization *
* * @return {void}
* @since 1.0.0 *
*/ * @since 1.0.0
constructor (lang = 'en-US') */
{ setPitch (pitch)
this.pitch = 1; {
this.rate = 1; this.pitch = pitch;
this.lang = lang; };
this.voices = [];
this.voice = null;
if (SpeechRecognition !== null) { /**
this.voices = window.speechSynthesis.getVoices(); * Set rate.
this.voice = this.voices[0]; *
} * @param {int} rate Rate
}; *
* @return {void}
*
* @since 1.0.0
*/
setRate (rate)
{
this.rate = rate;
};
/** /**
* Read text. * Get supported voices.
* *
* @param {string} text Text to read * @return {Array}
* *
* @return {void} * @since 1.0.0
* */
* @since 1.0.0 getVoices ()
*/ {
read (text) return this.voices;
{ };
/** global: SpeechSynthesisUtterance */ };
let utter = new SpeechSynthesisUtterance(text);
utter.lang = this.lang;
utter.voice = this.voice;
utter.pitch = this.pitch;
utter.rate = this.rate;
window.speechSynthesis.speak(utter); // todo: remove once obsolete
}; /** global: webkitSpeechRecognition */
/** global: SpeechRecognition */
var SpeechRecognition = typeof SpeechRecognition !== 'undefined' ? SpeechRecognition : typeof webkitSpeechRecognition !== 'undefined' ? webkitSpeechRecognition : null;
/** /** global: webkitSpeechGrammarList */
* Set Language. /** global: SpeechGrammarList */
* var SpeechGrammarList = typeof SpeechGrammarList !== 'undefined' ? SpeechGrammarList : typeof webkitSpeechGrammarList !== 'undefined' ? webkitSpeechGrammarList : null;
* @param {string} lang Language id (e.g. en-US)
*
* @return {void}
*
* @since 1.0.0
*/
setLanguage (lang)
{
this.lang = lang;
};
/** /** global: webkitSpeechRecognitionEvent */
* Set pitch. /** global: SpeechRecognitionEvent */
* var SpeechRecognitionEvent = typeof SpeechRecognitionEvent !== 'undefined' ? SpeechRecognitionEvent : typeof webkitSpeechRecognitionEvent !== 'undefined' ? webkitSpeechRecognitionEvent : null;
* @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 || {}));

View File

@ -6,172 +6,164 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class VoiceManager {
{ /**
"use strict"; * @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 */ if (SpeechRecognition !== null) {
jsOMS.Autoloader.defineNamespace('jsOMS.UI.Input.Voice'); this.recognition = new SpeechRecognition();
this.speechRecognitionList = new SpeechGrammarList();
}
};
// todo: remove once obsolete /**
/** global: webkitSpeechRecognition */ * Setup or re-initialize voice manager.
/** global: SpeechRecognition */ *
var SpeechRecognition = typeof SpeechRecognition !== 'undefined' ? SpeechRecognition : typeof webkitSpeechRecognition !== 'undefined' ? webkitSpeechRecognition : null; * @return {void}
*
* @since 1.0.0
*/
setup()
{
if (SpeechRecognition === null) {
return;
}
/** global: webkitSpeechGrammarList */ const self = this;
/** global: SpeechGrammarList */ this.recognition.lang = this.lang;
var SpeechGrammarList = typeof SpeechGrammarList !== 'undefined' ? SpeechGrammarList : typeof webkitSpeechGrammarList !== 'undefined' ? webkitSpeechGrammarList : null; this.recognition.interimResults = false;
this.recognition.maxAlternatives = 1;
this.recognition.continuous = true;
this.recognition.lang = this.lang;
/** global: webkitSpeechRecognitionEvent */ if (typeof this.commands !== 'undefined') {
/** global: SpeechRecognitionEvent */ this.speechRecognitionList.addFromString(this.getCommandsString(), 1);
var SpeechRecognitionEvent = typeof SpeechRecognitionEvent !== 'undefined' ? SpeechRecognitionEvent : typeof webkitSpeechRecognitionEvent !== 'undefined' ? webkitSpeechRecognitionEvent : null; this.recognition.grammars = this.speechRecognitionList;
}
jsOMS.UI.Input.Voice.VoiceManager = class { this.recognition.onstart = function() {};
/** this.recognition.onresult = function(event)
* @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; let result = jsOMS.trim(event.results[event.resultIndex][0].transcript);
this.commands = commands;
this.lang = lang;
this.recognition = null;
this.speechRecognitionList = null;
if (SpeechRecognition !== null) { if (self.commands.hasOwnProperty(result)) {
this.recognition = new SpeechRecognition(); self.commands[result]();
this.speechRecognitionList = new SpeechGrammarList();
} }
}; };
/** this.recognition.onspeechend = function()
* Setup or re-initialize voice manager.
*
* @return {void}
*
* @since 1.0.0
*/
setup()
{ {
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);
};
}; };
/** this.recognition.onnomatch = function(event)
* Create commands/grammar string from commands
*
* @return {string}
*
* @since 1.0.0
*/
getCommandsString()
{ {
return '#JSGF V1.0; grammar phrase; public <phrase> = ' + Object.keys(this.commands).join(' | ') + ' ;'; jsOMS.Log.Logger.instance.warning('Couldn\'t recognize speech');
}; };
/** this.recognition.onerror = function(event)
* Set language
*
* @param {string} lang Language code (e.g. en-US)
*
* @return {void}
*
* @since 1.0.0
*/
setLanguage(lang)
{ {
// todo: eventually restart jsOMS.Log.Logger.instance.warning('Error during speech recognition: ' + event.error);
this.recognition.lang = lang;
}; };
};
/** /**
* Add command/grammar and callback. * Create commands/grammar string from commands
* *
* @param {string} command Command id * @return {string}
* @param {callback} callback Callback for command *
* * @since 1.0.0
* @return {void} */
* getCommandsString()
* @since 1.0.0 {
*/ return '#JSGF V1.0; grammar phrase; public <phrase> = ' + Object.keys(this.commands).join(' | ') + ' ;';
add(command, callback) };
{
this.commands[command] = callback;
};
/** /**
* Start voice listener. * Set language
* *
* @return {void} * @param {string} lang Language code (e.g. en-US)
* *
* @since 1.0.0 * @return {void}
*/ *
start() * @since 1.0.0
{ */
if (SpeechRecognition === null) { setLanguage(lang)
return; {
} // 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. * Start voice listener.
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
stop() start()
{ {
if (SpeechRecognition === null) { if (SpeechRecognition === null) {
return; return;
} }
this.recognition.stop(); this.recognition.start();
}; };
}
}(window.jsOMS = window.jsOMS || {})); /**
* 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;

View File

@ -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. * UI manager for handling basic ui elements.
* *
@ -6,163 +13,155 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class UIManager {
{ /**
"use strict"; * @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 */ const self = this;
jsOMS.Autoloader.defineNamespace('jsOMS.UI'); /** global: MutationObserver */
this.domObserver = new MutationObserver(function(mutations) {
const length = mutations.length;
jsOMS.UI.UIManager = class { for(let i = 0; i < length; ++i) {
/** self.app.eventManager.trigger(mutations[i].target.id + '-' + mutations[i].type, 0, mutations[i]);
* @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);
}
} }
}; });
};
/** /**
* Get tab manager. * Bind & rebind UI elements.
* *
* @return {Object} * @param {string} [id] Element id
* *
* @since 1.0.0 * @return {void}
*/ *
getFormManager() * @since 1.0.0
{ */
return this.formManager; 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) {
* Get action manager. return;
* }
* @return {Object}
*
* @since 1.0.0
*/
getActionManager()
{
return this.actionManager;
};
/** switch (tag.tagName) {
* Get drag and drop manager. case 'form':
* this.formManager.bind(id);
* @return {Object} break;
* case 'table':
* @since 1.0.0 this.tableManager.bind(id);
*/ break;
getDragNDrop() default:
{ this.actionManager.bind(tag);
return this.dragNDrop; }
}; }
};
/** /**
* Get tab manager. * Get tab manager.
* *
* @return {Object} * @return {Object}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getTabManager() getFormManager()
{ {
return this.tabManager; return this.formManager;
}; };
/** /**
* Get table manager. * Get action manager.
* *
* @return {Object} * @return {Object}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getTableManager() getActionManager()
{ {
return this.tabManager; return this.actionManager;
}; };
/** /**
* Get DOM observer * Get drag and drop manager.
* *
* @return {Object} * @return {Object}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getDOMObserver() getDragNDrop()
{ {
return this.domObserver; return this.dragNDrop;
}; };
/** /**
* Get general UI * Get tab manager.
* *
* @return {Object} * @return {Object}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getGeneralUI() getTabManager()
{ {
return this.generalUI; return this.tabManager;
}; };
}
}(window.jsOMS = window.jsOMS || {})); /**
* 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;
};
};

View File

@ -14,7 +14,7 @@
window.addEventListener('error', function (e) window.addEventListener('error', function (e)
{ {
/** global: jsOMS */ /** global: jsOMS */
jsOMS.Log.Logger.instance.error(e.error); //jsOMS.Log.Logger.instance.error(e.error);
return false; return false;
}); });

View File

@ -8,319 +8,311 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class Http {
{ /**
"use strict"; * @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 */ this.set(uri);
jsOMS.Autoloader.defineNamespace('jsOMS.Uri.Http'); };
jsOMS.Uri.Http = class { /**
/** * Parse uri
* @constructor *
* * @param {string} str Url to parse
* @since 1.0.0 * @param {string} [mode] Parsing mode
*/ *
constructor(uri) * @return {Object}
{ *
this.uri = ''; * @throws {Error}
this.scheme = ''; *
this.host = ''; * @since 1.0.0
this.port = ''; */
this.user = ''; static parseUrl (str, mode = 'php')
this.pass = ''; {
this.query = null; const key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port',
this.queryString = ''; 'relative', 'path', 'directory', 'file', 'query', 'fragment'
this.fragment = ''; ],
this.base = ''; parser = {
this.root = '/'; 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);
}
/** const m = parser[mode].exec(str),
* Parse uri uri = {};
* let i = 14;
* @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)
};
if (!parser.hasOwnProperty(mode)) { while (--i) {
throw new Error('Unexpected parsing mode.', 'UriFactory', 52); if (m[i]) {
uri[key[i]] = m[i];
} }
}
const m = parser[mode].exec(str), delete uri.source;
uri = {};
let i = 14;
while (--i) { return uri;
if (m[i]) { };
uri[key[i]] = m[i];
/**
* 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; if (!key.length) {
}; continue;
/**
* 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 (typeof params[key] === 'undefined') {
params[key] = [];
}
params[key].push(keyValPairs[pairNum].split('=')[1]);
} }
}
return params; return params;
}; };
/** /**
* Set uri. * Set uri.
* *
* @param {string} uri Uri string * @param {string} uri Uri string
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
set (uri) set (uri)
{ {
this.uri = 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.scheme = parsed['scheme'];
this.host = parsed['host']; this.host = parsed['host'];
this.port = parsed['port']; this.port = parsed['port'];
this.user = parsed['user']; this.user = parsed['user'];
this.pass = parsed['pass']; this.pass = parsed['pass'];
this.path = parsed['path']; this.path = parsed['path'];
if (this.path.endsWith('.php')) { if (this.path.endsWith('.php')) {
this.path = this.path.substr(0, -4); 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) { if (this.queryString !== null) {
this.query = jsOMS.Uri.Http.getAllUriQueryParameters(this.queryString); this.query = Http.getAllUriQueryParameters(this.queryString);
} }
this.fragment = typeof parsed['fragment'] !== 'undefined' ? parsed['fragment'] : ''; this.fragment = typeof parsed['fragment'] !== 'undefined' ? parsed['fragment'] : '';
this.base = this.scheme + '://' + this.host + this.root; this.base = this.scheme + '://' + this.host + this.root;
}; };
/** /**
* Set root path. * Set root path.
* *
* @param {string} rootPath Uri root path * @param {string} rootPath Uri root path
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
setRootPath(rootPath) setRootPath(rootPath)
{ {
this.root = rootPath; this.root = rootPath;
this.set(this.uri); this.set(this.uri);
}; };
/** /**
* Get Uri base * Get Uri base
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getBase() getBase()
{ {
return this.base; return this.base;
}; };
/** /**
* Get Uri scheme * Get Uri scheme
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getScheme() getScheme()
{ {
return this.scheme; return this.scheme;
}; };
/** /**
* Get Uri host * Get Uri host
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getHost() getHost()
{ {
return this.host; return this.host;
}; };
/** /**
* Get Uri port * Get Uri port
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getPort() getPort()
{ {
return this.port; return this.port;
}; };
/** /**
* Get Uri user * Get Uri user
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getUser() getUser()
{ {
return this.user; return this.user;
}; };
/** /**
* Get Uri pass * Get Uri pass
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getPass() getPass()
{ {
return this.pass; return this.pass;
}; };
/** /**
* Get Uri query * Get Uri query
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getQuery() getQuery()
{ {
return this.queryString; return this.queryString;
}; };
/** /**
* Get Uri * Get Uri
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getUri() getUri()
{ {
return this.uri; return this.uri;
}; };
/** /**
* Get Uri fragment * Get Uri fragment
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getFragment() getFragment()
{ {
return this.fragment; return this.fragment;
}; };
/** /**
* Get Uri path * Get Uri path
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getPath() getPath()
{ {
return this.path; return this.path;
}; };
/** /**
* Get Uri path offset * Get Uri path offset
* *
* @return {int} * @return {int}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getPathOffset() getPathOffset()
{ {
return jsOMS.substr_count(this.root, '/') - 1; return jsOMS.substr_count(this.root, '/') - 1;
}; };
} };
}(window.jsOMS = window.jsOMS || {}));

View File

@ -1,3 +1,5 @@
import { Http } from './Http.js';
/** /**
* Uri factory. * Uri factory.
* *
@ -6,251 +8,244 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class UriFactory {
{
"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]);
}
}
};
}
/** /**
* 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 * @since 1.0.0
*/ */
jsOMS.Uri.UriFactory.uri = {}; static setQuery (key, value, overwrite)
}(window.jsOMS = window.jsOMS || {})); {
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 = {};

View File

@ -10,462 +10,455 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) export class FormView {
{ /**
"use strict"; * @constructor
/** @namespace jsOMS.Views */ *
jsOMS.Autoloader.defineNamespace('jsOMS.Views'); * @param {string} id Form id
*
* @since 1.0.0
*/
constructor (id)
{
this.id = id;
jsOMS.Views.FormView = class { this.initializeMembers();
/** this.bind();
* @constructor
*
* @param {string} id Form id
*
* @since 1.0.0
*/
constructor (id)
{
this.id = id;
this.initializeMembers(); this.success = null;
this.bind(); this.finally = null;
this.lastSubmit = 0;
};
this.success = null; /**
this.finally = null; * Initialize members
this.lastSubmit = 0; *
}; * 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 * Get method
* *
* Pulled out since this is used in a cleanup process * @return {string}
* *
* @return {void} * @since 1.0.0
* */
* @since 1.0.0 getMethod ()
*/ {
initializeMembers () return this.method;
{ };
this.submitInjects = [];
this.method = 'POST';
this.action = '';
};
/** /**
* Get method * Get action
* *
* @return {string} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getMethod () getAction ()
{ {
return this.method; return this.action;
}; };
/** /**
* Get action * Get time of last submit
* *
* @return {string} * @return {int}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getAction () getLastSubmit ()
{ {
return this.action; return this.lastSubmit;
}; };
/** /**
* Get time of last submit * Update last submit time
* *
* @return {int} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getLastSubmit () updateLastSubmit ()
{ {
return this.lastSubmit; this.lastSubmit = Math.floor(Date.now());
}; };
/** /**
* Update last submit time * Get submit elements
* *
* @return {void} * @return {Object}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
updateLastSubmit () getSubmit ()
{ {
this.lastSubmit = Math.floor(Date.now()); 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 * Get success callback
* *
* @return {Object} * @return {callback}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getSubmit () getSuccess ()
{ {
return document.querySelectorAll( return this.success;
'#' + this.id + ' input[type=submit], ' };
+ 'button[form=' + this.id + '][type=submit], '
+ '#' + this.id + ' button[type=submit], '
+ '#' + this.id + ' .submit'
);
};
/** /**
* Get success callback * Set success callback
* *
* @return {callback} * @param {callback} callback Callback
* *
* @since 1.0.0 * @return {void}
*/ *
getSuccess () * @since 1.0.0
{ */
return this.success; setSuccess (callback)
}; {
this.success = callback;
};
/** /**
* Set success callback * Get finally callback
* *
* @param {callback} callback Callback * @return {callback}
* *
* @return {void} * @since 1.0.0
* */
* @since 1.0.0 getFinally() {
*/ return this.finally;
setSuccess (callback) };
{
this.success = callback;
};
/** /**
* Get finally callback * Set finally callback
* *
* @return {callback} * @param {callback} callback Callback
* *
* @since 1.0.0 * @return {void}
*/ *
getFinally() { * @since 1.0.0
return this.finally; */
}; setFinally(callback) {
this.finally = callback;
};
/** /**
* Set finally callback * Inject submit with post callback
* *
* @param {callback} callback Callback * @param {callback} callback Callback
* *
* @return {void} * @return {void}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
setFinally(callback) { injectSubmit (callback)
this.finally = callback; {
}; this.submitInjects.push(callback);
};
/** /**
* Inject submit with post callback * Get form elements
* *
* @param {callback} callback Callback * @return {Array}
* *
* @return {void} * @since 1.0.0
* */
* @since 1.0.0 getFormElements ()
*/ {
injectSubmit (callback) const form = document.getElementById(this.id);
{
this.submitInjects.push(callback);
};
/** if (!form) {
* Get form elements return [];
* }
* @return {Array}
*
* @since 1.0.0
*/
getFormElements ()
{
const form = document.getElementById(this.id);
if (!form) { const selects = form.getElementsByTagName('select'),
return []; 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'), // todo: handle radio here as well
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 return Array.prototype.slice.call(inputs).concat(
// the reason for this is, there may be multiple buttons in a form which trigger a send Array.prototype.slice.call(selects),
// sometimes even a checkbox or drop down could trigger a send Array.prototype.slice.call(textareas),
// Maybe it makes sense to do this however at a different place e.g. the actual data submit 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) { * Get unique form elements
delete inputs[i]; *
* @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( return data;
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; });
};
/** /**
* Get unique form elements * Get form id
* *
* @param {Array} arr Form element array * @return {string}
* *
* @return {Array} * @since 1.0.0
* */
* @since 1.0.0 getId ()
*/ {
getUniqueFormElements (arr) return this.id;
{ };
let seen = {};
return arr.filter(function(item) { /**
return seen.hasOwnProperty(item.name) ? false : (seen[item.name] = true); * Validate form
}); *
}; * @return {boolean}
*
/** * @since 1.0.0
* Get form data */
* isValid ()
* @return {Object} {
* const elements = this.getFormElements(),
* @since 1.0.0 length = elements.length;
*/
getData ()
{
const data = {},
elements = this.getFormElements(),
length = elements.length;
let value = null;
try {
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
if (elements[i].tagName.toLowerCase() === 'canvas') { if ((elements[i].required && elements[i].value === '')
value = elements[i].toDataURL('image/png'); || (typeof elements[i].pattern !== 'undefined'
} else { && elements[i].pattern !== ''
if (typeof elements[i].value !== 'undefined') { && !(new RegExp(elements[i].pattern)).test(elements[i].value))
value = elements[i].value; ) {
} else if (typeof elements[i].getAttribute('data-value') !== 'undefined') { return false;
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;
} }
} }
} catch (e) {
jsOMS.Log.Logger.instance.error(e);
}
return data; return true;
}; };
/** /**
* Get form id * Get form element
* *
* @return {string} * @return {Object}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
getId () getElement ()
{ {
return this.id; return document.getElementById(this.getId());
}; };
/** /**
* Validate form * Get form element id
* *
* @return {boolean} * @return {string}
* *
* @since 1.0.0 * @since 1.0.0
*/ */
isValid () static getElementId (e)
{ {
const elements = this.getFormElements(), if (e.getAttribute('name') !== null) {
length = elements.length; 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 { return null;
for (let i = 0; i < length; ++i) { };
if ((elements[i].required && elements[i].value === '')
|| (typeof elements[i].pattern !== 'undefined' /**
&& elements[i].pattern !== '' * Get submit injects
&& !(new RegExp(elements[i].pattern)).test(elements[i].value)) *
) { * @return {Object}
return false; *
} * @since 1.0.0
} */
} catch (e) { getSubmitInjects ()
jsOMS.Log.Logger.instance.error(e); {
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;
/** for (let i = 0; i < length; ++i) {
* Get form element switch (elements[i].tagName) {
* case 'input':
* @return {Object} jsOMS.UI.Input.unbind(elements[i]);
* break;
* @since 1.0.0 case 'select':
*/ this.bindSelect(elements[i]);
getElement () break;
{ case 'textarea':
return document.getElementById(this.getId()); this.bindTextarea(elements[i]);
}; break;
case 'button':
/** this.bindButton(elements[i]);
* Get form element id break;
* default:
* @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');
} }
}
};
return null; /**
}; * Clean form
*
/** * @return {void}
* Get submit injects *
* * @since 1.0.0
* @return {Object} */
* clean ()
* @since 1.0.0 {
*/ this.unbind();
getSubmitInjects () this.initializeMembers();
{ };
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 || {}));

View File

@ -6,157 +6,151 @@
* @version 1.0.0 * @version 1.0.0
* @since 1.0.0 * @since 1.0.0
*/ */
(function (jsOMS) { export class TableView {
"use strict"; /**
* @constructor
*
* @since 1.0.0
*/
constructor (id) {
this.id = id;
jsOMS.Autoloader.defineNamespace('jsOMS.Views'); this.bind();
};
jsOMS.Views.TableView = class { /**
/** * Bind the table
* @constructor *
* * @return {void}
* @since 1.0.0 *
*/ * @since 1.0.0
constructor (id) { */
this.id = id; 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: []
}; };
/** data.caption = table.getElementsByTagName('caption')[0].innerText;
* Bind the table
*
* @return {void}
*
* @since 1.0.0
*/
bind ()
{
const e = document.getElementById(this.id);
};
/** const header = table.querySelectorAll('thead tr td, thead tr th'),
* Serialize table data headerLength = header.length;
*
* @return {object}
*
* @since 1.0.0
*/
serialize()
{
const table = document.getElementById(this.id);
let data = {
caption: null,
header: [],
rows: []
};
data.caption = table.getElementsByTagName('caption')[0].innerText; for (let i = 0; i < headerLength; ++i) {
data.header.push(header[i].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;
} }
/** const rows = table.querySelectorAll('tbody tr'),
* Get table export button rowsLength = rows.length;
*
* @return {HTMLElement}
*
* @since 1.0.0
*/
getExport()
{
return document.querySelectorAll('#' + this.id + ' .download')[0];
};
/** for (let i = 0; i < rowsLength; ++i) {
* Get table header elements which provide sorting data.rows[i] = [];
*
* @return {array}
*
* @since 1.0.0
*/
getSorting()
{
return document.querySelectorAll(
'#' + this.id + ' thead .sort-asc,'
+ ' #' + this.id + ' thead .sort-desc'
);
};
/** const columns = rows[i].querySelectorAll('td, th'),
* Get table header elements which provide filter functionality columnLength = columns.length;
*
* @return {array}
*
* @since 1.0.0
*/
getFilter()
{
return document.querySelectorAll(
'#' + this.id + ' thead .filter'
);
};
/** for (let j = 0; j < columnLength; ++j) {
* Get row elements which allow to swap the current row with another row data.rows[i].push(columns[j].innerText);
* }
* @return {array} }
*
* @since 1.0.0
*/
getSortableRows()
{
return document.querySelectorAll(
'#' + this.id + ' tbody .order-up,'
+ ' #' + this.id + ' tbody .order-down'
);
};
/** return data;
* 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'
);
};
} }
}(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'
);
};
};