/** Datei: themes/lcars/assets.OLD/js/arunox/tools.beep.js **/ window.ARUNOX ??= {}; ARUNOX.Tools ??= {}; var audioCtx = new ( window.AudioContext || window.webkitAudioContext || window.audioContext ); ARUNOX.Tools.Beep = (duration, frequency, volume, type, callback) => { var oscillator = audioCtx.createOscillator(); var gainNode = audioCtx.createGain(); oscillator.connect(gainNode); gainNode.connect(audioCtx.destination); if (volume) { gainNode.gain.value = volume; } if (frequency) { oscillator.frequency.value = frequency; } if (type) { oscillator.type = type; } if (callback) { oscillator.onended = callback; } oscillator.start(audioCtx.currentTime); oscillator.stop(audioCtx.currentTime + ((duration || 500) / 1000)); }; ARUNOX.Tools.Beep.short = () => { ARUNOX.Tools.Beep(100, 600, 1, 'square') }; ARUNOX.Tools.Beep.long = () => { ARUNOX.Tools.Beep(300, 600, 1, 'square') }; ARUNOX.Tools.Beep.alert = () => { ARUNOX.Tools.Beep(100, 900, 1, 'square') window.setTimeout( () => { ARUNOX.Tools.Beep(100, 900, 1, 'square') }, 100 ); }; /** Datei: themes/lcars/assets.OLD/js/arunox/components/section/navbar.js **/ /** * /lcars/components/section/navbar.js * * Some Javascript codes without further description * * @author Sparky * @copyright 2025 ARUNOX * @version 2.0.0 * @since 2.0.0 Adaptation to new ctx method * @since 1.0.0 File is created */ ARUNOX.Templates.register( 'layout/section/navbar', { htmlTag : 'nav', hooks : { config : function( config ) { config.datasets.arx.node = this.instance.htmlTag; config.classes.push( 'frame__navbar', `frame__navbar--${this.instance.htmlTag}` ); return config; }, corner : function( config, position ) { return Object.assign( { id : `${this.instance.parent.config.name}_${position}`, classes : [ 'frame__wrapper', 'frame__element', `frame__navbar--${position}` ], keepOnReplace : { classes : [ 'frame__*' ], }, content : [ ARUNOX.Templates.config( 'div', { classes : [ 'frame__wrapper__inner' ], }), ], }, config || {} ); }, toolbar : function( config, position ) { return Object.assign( { id : `${this.instance.parent.config.name}_${position}`, classes : [ 'frame__wrapper', `frame__navbar--${position}` ], keepOnReplace : { classes : [ 'frame__*' ], }, content : [ ARUNOX.Templates.config( 'div', { classes : [ 'frame__wrapper__inner' ], content : typeof config.textNode === 'string' ? [ ARUNOX.Templates.config( this.instance.config.html || 'div', { classes : [ 'frame__title' ], content : config.textNode, }) ] : config.content, }), ], }, config || {} ); }, nodeRight : function( config ) { return this.instance.filter( 'corner', config || {}, 'right' ); }, nodeBefore : function( config ) { return this.instance.filter( 'toolbar', config || {}, 'before' ); }, nodeCenter : function( config ) { return this.instance.filter( 'toolbar', config || {}, 'center' ); }, nodeAfter : function( config ) { return this.instance.filter( 'toolbar', config || {}, 'after' ); }, nodeLeft : function( config ) { if( this.instance.parent.config.aside.visibility ) { config = Object.assignRecursive( {}, config || {}, { classes : [ 'frame__element', 'frame__element--corner' ], datasets : { arx : { node : 'corner', }, }, }); } return this.instance.filter( 'corner', config || {}, 'left' ); }, }, builder : function( config, data ) { const fillBefore= this.render( 'div', { classes : [ 'frame__element', 'frame__element--fill' ], datasets : { arx : { node : 'fillBefore', }, } }); const fillAfter = this.render( 'div', { classes : [ 'frame__element', 'frame__element--fill' ], datasets : { arx : { node : 'fillAfter', }, } }); this.parent.root.classList.add( `frame--${this.htmlTag}-${config.size}` ); this.node( 'left', {}, 'prepend' ).render(); this.node( 'before', config.before, 'before', fillBefore ); this.node( 'center', config.center, 'before', fillAfter ); this.node( 'after', config.after, 'after', fillAfter ); this.node( 'right', {}, 'append' ).render(); if( config.before ) this.nodes.before.render(); if( config.center ) this.nodes.center.render(); if( config.after ) this.nodes.after.render(); }, }); ARUNOX.Templates.register( 'layout/section/header', { htmlTag : 'header', extends : 'layout/section/navbar', }); ARUNOX.Templates.register( 'layout/section/footer', { htmlTag : 'footer', extends : 'layout/section/navbar', }); /** Datei: themes/lcars/assets.OLD/js/arunox/components/section/sidebar.js **/ /** * /lcars/components/section/sidebar.js * * Some Javascript codes without further description * * @author Sparky * @copyright 2025 ARUNOX * @version 1.0.0 * @since 1.0.0 File is created */ ARUNOX.Templates.register( 'layout/section/sidebar', { htmlTag : 'aside', hooks : { config : function( config ) { config.datasets.arx.node = this.instance.htmlTag; config.classes.push( 'frame__sidebar' ); return config; }, toolbar : function( config, position ) { return Object.assign( { id : `${this.instance.parent.config.name}_${position}`, classes : [ 'frame__wrapper', `frame__sidebar--${position}` ], keepOnReplace : { classes : [ 'frame__*' ], }, content : [ ARUNOX.Templates.config( 'div', { classes : [ 'frame__wrapper__inner' ], content : config.content, }), ], }, config || {} ); }, nodeBefore : function( config ) { return this.instance.filter( 'toolbar', config || {}, 'before' ); }, nodeCenter : function( config ) { return this.instance.filter( 'toolbar', config || {}, 'center' ); }, nodeAfter : function( config ) { return this.instance.filter( 'toolbar', config || {}, 'after' ); }, shouldRender : function( render, config, data ) { return this.instance.parent.config.aside.visibility; }, }, builder : function( config, data ) { const fillBefore= this.render( 'div', { classes : [ 'frame__element', 'frame__element--fill' ], datasets : { arx : { node : 'fillBefore', }, } }); const fillAfter = this.render( 'div', { classes : [ 'frame__element', 'frame__element--fill' ], datasets : { arx : { node : 'fillAfter', }, } }); this.parent.root.classList.add( `frame--sidebar-${config.size}`, `frame--sidebar-${config.side}` ); this.node( 'before', config.before, 'before', fillBefore ); this.node( 'center', config.center, 'before', fillAfter ); this.node( 'after', config.after, 'after', fillAfter ); if( config.before ) this.nodes.before.render(); if( config.center ) this.nodes.center.render(); if( config.after ) this.nodes.after.render(); }, }); /** Datei: themes/lcars/assets.OLD/js/arunox/components/dynamic.js **/ /** * /lcars/components/dynamic.js * * Some Javascript codes without further description * * @author Sparky * @copyright 2025 ARUNOX * @version 1.0.0 * @since 1.0.0 File is created */ ARUNOX.Templates.register( 'dynamic', { extends : 'layout/section', hooks : { config : { priority : 5, callback : function( config, data ) { return { name : 'main_section_content', color : 'primary', header : { html : 'h2', after : config.title, }, aside : 'right', content : ARUNOX.Templates.config( 'div', { classes : [ 'frame__content' ], content : config?.content, }), footer : { after : config.copyright, }, }; }, }, }, }); /** Datei: themes/lcars/assets.OLD/js/arunox/components/section.js **/ /** * /lcars/components/section.js * * Some Javascript codes without further description * * @author Sparky * @copyright 2025 ARUNOX * @version 2.0.0 * @since 2.0.0 Adaptation to new ctx method * @since 1.0.0 File is created */ ARUNOX.Templates.register( 'layout/section', { htmlTag : 'section', hooks : { config : function( config, data ) { // console.log( 'SECTION', config ); config.size ??= 'sm'; config.aside ??= false; config.header ??= {}; config.footer ??= {}; config.content ??= true; config.color ??= 'default'; if( typeof config.aside !== 'undefined' ) { if( typeof config.aside === 'string' ) config.aside = { side : config.aside }; if( typeof config.aside === 'boolean' ) config.aside = { visibility : config.aside }; config.aside.visibility ??= true; config.aside.side ??= config.side || 'left'; config.aside.size ??= config?.size; } if( config.header ) { if( typeof config.header === 'string' ) config.header = { after : config.header }; if( typeof config.header === 'boolean' ) config.header = { visibility : config.header }; config.header.visibility ??= true; config.header.size ??= config?.size; } if( config.footer ) { if( typeof config.footer === 'string' ) config.footer = { after : config.footer }; if( typeof config.footer === 'boolean' ) config.footer = { visibility : config.footer }; config.footer.visibility ??= true; config.footer.size ??= config?.size; } // if( config.content ) { // if( typeof config.content === 'string' ) config.content = { textNode : config.content }; // // config.content.visibility = true; // } return config; }, content : function( content ) { if( content.length > 1 ) { return ARUNOX.Templates.config( 'div', { classes : [ 'frame__content' ], content : content, }); } if( content.length == 1 ) { content[0].config.classes ??= []; content[0].config.classes.push( 'frame__content' ); } return content; }, }, builder : function( config, data ) { config.name = config.name || 'section'; this.root.id = config.name; this.root.classList.add( 'frame__section' ); this.render( 'layout/section/header', config.header, data ) this.render( 'layout/section/sidebar', config.aside, data ) this.render( 'layout/section/footer', config.footer, data ) } }); /** Datei: themes/lcars/assets.OLD/js/arunox/hooks/button.js **/ /** * /lcars/hooks/button.js * * Some Javascript codes without further description * * @author Sparky * @copyright 2025 ARUNOX * @version 1.0.0 * @since 1.0.0 File is created */ ARUNOX.Hooks.register( 'button->config', function( config ) { return Object.assignRecursive( config, { block : 'frame', color : Object.assign( { color : 'primary', prefix : 'theme', }, config.color ), classes : [ config.classes, [ 'frame__element', 'frame__element--button', ]].flat().filter(Boolean), }); }, 5 ); if( 'vibrate' in navigator ) { ARUNOX.Hooks.register( 'button->afterRender', function() { this.instance.element.addEventListener( 'touchstart', event => { navigator.vibrate(50); }); }); } /** Datei: themes/lcars/assets.OLD/js/arunox/hooks/menus.js **/ /** * /lcars/hooks/_general.js * * Some Javascript codes without further description * * @author Sparky * @copyright 2025 ARUNOX * @version 1.0.0 * @since 1.0.0 File is created */ ARUNOX.Hooks.register( 'addMenus', async function( anchor ) { const wrapper = this.instance.replace( 'div' ); const routes = ( await ARUNOX.Router.routes() ).map( item => { if( !Array.isArray( item.menu ) ) { item.menu = [ item.menu ]; } return item; }); const filtered = routes.filter( item => item.menu.includes( anchor ) ); for( const route of filtered ) { if( route.path ) { wrapper.apply( 'addMenus->item', route ); continue; } wrapper.apply( 'addMenus->category', route, routes ); } }); ARUNOX.Hooks.register( 'addMenus->category', async function( route, routes ) { const filtered = routes.filter( item => item.menu.includes( route.name ) ); const wrapper = this.instance.render( 'div', { classes : [ 'frame__wrapper' ], content : ARUNOX.Templates.config( 'div', { classes : [ 'frame__element', 'frame__element--label' ], content : ARUNOX.Templates.config( 'span', { classes : [ 'label' ], content : route.label, }), }), }); for( const route of filtered ) { wrapper.apply( 'addMenus->item', route ); } }); ARUNOX.Hooks.register( 'addMenus->item', async function( route ) { this.instance.render( 'button', { label : route.label, icon : route.icon, action : route.path, }); }); /** Datei: themes/lcars/assets.OLD/js/arunox/hooks/form.js **/ /** * rest/arunox/hooks/form.js * * Some Javascript codes without further description * * @author Sparky * @copyright 2025 ARUNOX * @version 1.0.0 * @since 1.0.0 File is created */ ARUNOX.Hooks.register( 'form->afterRender', function() { const section = this.instance.closest( 'layout/section' ); const buttons = this.instance.nodes.buttons; if( section ) { section.nodes.footer.nodes.after.replace( buttons ); } }); /** Datei: themes/lcars/assets.OLD/js/arunox/hooks/notifications.js **/ /** * /lcars/hooks/notifications.js * * Some Javascript codes without further description * * @author Sparky * @copyright 2025 ARUNOX * @version 1.0.0 * @since 1.0.0 File is created */ ARUNOX.Hooks.register( 'notifications->afterRender', function() { const section = this.instance.closest( 'layout/section' ); if( section ) { section.nodes.header.nodes.before.render(); section.nodes.header.nodes.before.replace( this.instance ); this.instance.addNotification({ duration : 0, icon : 'bi-bell', title : 'Benachrichtigungen', message : 'Keine Benachrichtigungen', style : { order : -1, }, }); } }); ARUNOX.Hooks.register( 'notification->afterRender', function() { const config = this.instance.config; if( config.duration === 0 ) return; config.delay ??= 2000; config.animate ??= config.delay <= 500 ? 100 : 500; if( typeof ARUNOX.Tools.Beep === 'function' ) { if( config.type == 'danger' ) ARUNOX.Tools.Beep.alert(); else if( config.type == 'success' ) ARUNOX.Tools.Beep.short(); else if( config.type == 'warning' ) ARUNOX.Tools.Beep.long(); } window.setTimeout( () => { this.instance.parent.root.classList.add( 'hover' ); window.setTimeout( () => { this.instance.parent.root.classList.remove('hover'); // if( config.redirect !== false && config.redirect.url !== false ) { // if( config.redirect === true ) location.reload(); // else location.href = config.redirect.url; // } window.setTimeout( () => { this.instance.root.classList.add( 'fade-out' ); window.setTimeout( () => { this.instance.root.remove(); }, 250 ); }, config.message ? 2000 : 0 ); }, config.delay || 2000 ); }, config.animate || 500 ); }); /** Datei: themes/lcars/assets.OLD/js/arunox/templates/login.js **/ /** * rest/arunox/templates/login.js * * Some Javascript codes without further description * * @author Sparky * @copyright 2025 ARUNOX * @version 2.0.0 * @since 2.0.0 Adaptation to new ctx method * @since 1.0.0 File is created */ ARUNOX.Templates.register( 'login', { extends : 'layout/section', hooks : { config : { priority : 5, callback : function( config, data ) { return { name : 'main_section', size : isMobile ? 'sm' : 'md', header : { html : 'h1', after : config.title, }, content : config?.content, footer : { left : { arx : { ref : 'reload', }, }, after : config.copyright, }, }; }, }, dynamicConfig : { once : true, priority : 6, hook : 'config', template : 'dynamic', callback : function( config, data ) { const loginConfig = { title : 'Login required', message : [ 'Enter login details' ], }; return Object.assignRecursive( config, { color : 'danger', header : { after : false, before : 'Locked', }, aside : { side : 'left', }, content : [ ARUNOX.Templates.config( 'div', { classes : [ 'error__wrapper' ], content : [ ARUNOX.Templates.config( 'div', { classes : 'error', content : [ ARUNOX.Templates.config( 'div', { classes : 'error__icon', innerHTML : ``, }), ARUNOX.Templates.config( 'div', { classes : 'error__text', content : [ ARUNOX.Templates.config( 'h1', { classes : 'error__caption', content : loginConfig.title, }), ARUNOX.Templates.config( 'div', { classes : 'error__message', content : loginConfig.message.join(' or '), }), ], }), ], }), ], }), ] }); }, }, afterRender : function( config, data ) { this.instance.container.classList.removeRexEx( /template--.*/ ); this.instance.container.classList.add( 'theme', 'template--login' ); this.instance.nodes.footer.nodes.left.replace( 'button', { icon : 'bi bi-arrow-clockwise', title : 'Reload', color : { color: 'danger', target: 'button' }, href : 'javascript:location.reload( true );void(0);', target : '_top', }); this.instance.render( 'notifications' ); }, }, }); /** Datei: themes/lcars/assets.OLD/js/arunox/templates/default.js **/ ARUNOX.Templates.register( 'default', { extends : 'layout/section', hooks : { config : { priority : 5, callback : function( config, data ) { return { name : 'main_section', header : { html : 'h1', size : ARUNOX.Utils.device.isMobile ? 'sm' : 'md', after : config.title, }, aside : { size : 'xl', }, content : config?.content, footer : { after : config.copyright, }, }; }, }, afterRender : function( config, data ) { this.instance.container.classList.removeRexEx( /template--.*/ ); this.instance.container.classList.add( 'theme' ); this.instance.nodes.footer.nodes.before.apply( 'addMenus', 'tools' ); this.instance.nodes.aside.nodes.before.apply( 'addMenus', 'sidebar' ); this.instance.render( 'notifications' ); }, }, }); /** Datei: themes/lcars/assets.OLD/js/arunox/app.js **/ ARUNOX.Utils.dom.ready(async () => { try { // await ARUNOX.Loader.loadAll([ // '/assets/js/hooks/_general.js', // '/themes/lcars/js/hooks/button.js', // '/themes/lcars/js/hooks/notifications.js', // // '/themes/lcars/js/components/section.js', // '/themes/lcars/js/components/dynamic.js', // '/themes/lcars/js/templates/default.js', // ]); ARUNOX.currentTheme = 'lcars'; ARUNOX.themeHookPath = `/themes/${ARUNOX.currentTheme}/js/hooks`; ARUNOX.themeComponentPath = `/assets/js/components`; await ARUNOX.Router.handle( window.location.pathname + window.location.hash, {}, {}, 'rest' ); } catch( error ) { console.error( 'Failed to initialize app:', error ); } }); /** Datei: themes/lcars/assets.OLD/js/arunox/tools.keyboard.js **/ window.ARUNOX ??= {}; ARUNOX.Tools ??= {}; ARUNOX.Tools.Keyboard = { _value : '', onHide : null, onShow : null, onAdd : null, onRefresh : null, onClear : null, onClearShow : null, onClearHide : null, onBack : null, onBackShow : null, onBackHide : null, Types : { numbers : [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ], letters : [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'X', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ], base16 : [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' ], base36 : [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'X', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ], }, prefix : '#', type : 'numbers', keys : [], keyConfig : {}, visible : true, content : null, number : null, openBtn : null, closeBtn : null, backBtn : null, clearBtn : null, add : function( key ) { this._value += key; this.refresh(); this._call( this.onAdd ); }, clear : function() { this._value = ''; this.refresh(); this._call( this.onClear ); }, backspace : function() { this._value = this._value.substring( 0, this._value.length - 1 ); this.refresh(); this._call( this.onBack ); }, refresh : function() { this._call( this.onBackHide ); this._call( this.onClearHide ); if( this.number ) { this.number.element.innerText = this.prefix + this._value; this._call( this.onRefresh, this._value ); } if( this._value ) { this._call( this.onBackShow ); this._call( this.onClearShow ); } }, hide : function( onHide ) { this._call( onHide || this.onHide ); }, show : function( onShow ) { this._call( onShow || this.onShow ); }, init : function( options ) { Object.assign( this, {}, options || {} ); if( this.closeBtn ) { this.closeBtn.element.href = 'javascript:ARUNOX.Tools.Keyboard.hide();void(0);'; this.closeBtn.element.target = '_top'; } if( this.openBtn ) { this.openBtn.element.href = 'javascript:ARUNOX.Tools.Keyboard.show();void(0);'; this.openBtn.element.target = '_top'; } if( this.backBtn ) { this.backBtn.element.href = 'javascript:ARUNOX.Tools.Keyboard.backspace();void(0);'; this.backBtn.element.target = '_top'; } if( this.clearBtn ) { this.clearBtn.element.href = 'javascript:ARUNOX.Tools.Keyboard.clear();void(0);'; this.clearBtn.element.target = '_top'; } if( this.content ) { if( !this.keys.length ) this.keys = this.Types[ this.type ]; else this.type = 'custom'; this.content.element.classList.add( 'keyboard', `keybaord--${this.type}` ); this.content.element.style.setProperty( '--tiles', this.keys.length ) this.content.element.style.setProperty( '--columns', Math.ceil( Math.sqrt( this.keys.length ) ) ) this.content.element.style.setProperty( '--rows', Math.floor( Math.sqrt( this.keys.length ) ) ) for( const key of this.keys ) { this.content.render( 'button', Object.assign( { color : 'default', label : key, onClick : () => this.add( key ), }, this.keyConfig ) ); } } this.refresh(); if( this.visible ) this.show(); else this.hide(); }, _call : function( callback, ...args ) { if( typeof callback === 'function' ) { return callback.apply( this, args ); } return false; }, };