Skip to content

Commit

Permalink
some documentation
Browse files Browse the repository at this point in the history
lenadax committed Aug 22, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent a50135d commit ca9631b
Showing 5 changed files with 207 additions and 23 deletions.
3 changes: 3 additions & 0 deletions js/src/globals.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import ts from 'treibstoff';

/**
* Class to manage global events.
*/
export class GlobalEvents extends ts.Events {

/**
44 changes: 41 additions & 3 deletions js/src/header.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import $ from 'jquery';
import ts from 'treibstoff';
import {ScrollbarY} from './scrollbar.js';
import {LayoutAware} from './layout.js';
import { ScrollbarY } from './scrollbar.js';
import { LayoutAware } from './layout.js';

/**
* Class to manage the header layout and interactions.
* @extends LayoutAware
*/
export class Header extends LayoutAware {

/**
* Initializes the Header instance.
* @param {Element} context
*/
static initialize(context) {
const elem = ts.query_elem('#header-main', context);
if (!elem) {
@@ -13,6 +21,9 @@ export class Header extends LayoutAware {
new Header(elem);
}

/**
* @param {Element} elem The main header element.
*/
constructor(elem) {
super(elem);
this.elem = elem;
@@ -25,7 +36,6 @@ export class Header extends LayoutAware {
this.mainmenu = ts.query_elem('#mainmenu', elem);
this.mainmenu_elems = $('.nav-link.dropdown-toggle', this.mainmenu);

// this.render_mobile_scrollbar = this.render_mobile_scrollbar.bind(this);
this.mainmenu_elems.each((i, el) => {
$(el).on('shown.bs.dropdown', this.render_mobile_scrollbar.bind(this));
$(el).on('hidden.bs.dropdown', this.render_mobile_scrollbar.bind(this));
@@ -40,6 +50,9 @@ export class Header extends LayoutAware {
this.render_mobile_scrollbar = this.render_mobile_scrollbar.bind(this);
}

/**
* Destroys the Header instance and cleans up event listeners.
*/
destroy() {
super.destroy();
this.mainmenu_elems.each((i, el) => {
@@ -51,26 +64,43 @@ export class Header extends LayoutAware {
wrapper.off('hide.bs.collapse hidden.bs.collapse', this.set_mobile_menu_closed);
}

/**
* Renders the mobile scrollbar if in compact mode.
*/
render_mobile_scrollbar() {
if (this.is_compact && this.mobile_scrollbar) {
this.mobile_scrollbar.render();
}
}

/**
* Binds event listeners for navbar collapse events.
*/
bind() {
const wrapper = this.navbar_content_wrapper;
wrapper.on('show.bs.collapse shown.bs.collapse', this.set_mobile_menu_open);
wrapper.on('hidden.bs.collapse', this.set_mobile_menu_closed);
}

/**
* Sets a header classto indicate the mobile menu is open.
*/
set_mobile_menu_open() {
this.elem.addClass('mobile-menu-open');
}

/**
* Removes a header class to indicate the mobile menu is closed.
*/
set_mobile_menu_closed() {
this.elem.removeClass('mobile-menu-open');
}

/**
* Handles changes (scrollbar and bootstrap dropdown)
* in the compact state of the header.
* @param {boolean} val
*/
on_is_compact(val) {
if (val) {
this.elem.removeClass('full').removeClass('navbar-expand');
@@ -103,6 +133,10 @@ export class Header extends LayoutAware {
}
}

/**
* Handles changes in the super compact state of the header.
* @param {boolean} val
*/
on_is_super_compact(val) {
const in_navbar_content = ts.query_elem(
'#personaltools',
@@ -121,6 +155,10 @@ export class Header extends LayoutAware {
}
}

/**
* Handles changes in the sidebar collapsed state.
* @param {boolean} val
*/
on_is_sidebar_collapsed(val) {
if (val) {
this.logo_placeholder.show();
59 changes: 58 additions & 1 deletion js/src/layout.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import $ from 'jquery';
import ts from 'treibstoff';
import {global_events} from './globals.js';
import { global_events } from './globals.js';

/**
* Class to manage the main area of the application.
* @extends ts.Events
*/
export class MainArea extends ts.Events {

/**
* Initializes the MainArea instance.
* @param {Element} context
*/
static initialize(context) {
const elem = ts.query_elem('#main-area', context);
if (!elem) {
@@ -12,6 +20,9 @@ export class MainArea extends ts.Events {
new MainArea(elem);
}

/**
* @param {Element} elem The main area element.
*/
constructor(elem) {
super();
this.elem = elem;
@@ -27,16 +38,26 @@ export class MainArea extends ts.Events {
ts.ajax.attach(this, elem);
}

/**
* Destroys the MainArea instance and cleans up event listeners.
*/
destroy() {
$(window).off('resize', this.set_mode);
global_events.off('on_sidebar_resize', this.set_mode);
}

/**
* Sets the compact state based on the current width of the main area element.
*/
set_mode() {
this.is_compact = this.elem.outerWidth() < 992; // tablet
this.is_super_compact = this.elem.outerWidth() < 576; // mobile
}

/**
* Handles changes in the compact state of the main area.
* @param {boolean} val
*/
on_is_compact(val) {
if (val) {
this.elem.removeClass('full');
@@ -49,6 +70,10 @@ export class MainArea extends ts.Events {
global_events.trigger('on_main_area_mode', this);
}

/**
* Handles changes in the super compact state of the main area.
* @param {boolean} val
*/
on_is_super_compact(val) {
if (val) {
this.elem.addClass('super-compact');
@@ -60,8 +85,15 @@ export class MainArea extends ts.Events {
}
}

/**
* Base class for subclasses that inherit layout-aware behavior.
* @extends ts.Events
*/
export class LayoutAware extends ts.Events {

/**
* @param {Element} elem
*/
constructor(elem) {
super();
this.elem = elem;
@@ -79,16 +111,28 @@ export class LayoutAware extends ts.Events {
ts.ajax.attach(this, elem);
}

/**
* Destroys the LayoutAware instance and cleans up event listeners.
*/
destroy() {
global_events.off('on_main_area_mode', this.set_mode);
global_events.off('on_sidebar_resize', this.on_sidebar_resize);
}

/**
* Sets the layout mode based on the main area's state.
* @param {} inst
* @param {MainArea} mainarea
*/
set_mode(inst, mainarea) {
this.is_compact = mainarea.is_compact;
this.is_super_compact = mainarea.is_super_compact;
}

/**
* Handles changes in the compact state of the main area layout.
* @param {boolean} val Indicates if the main area layout is compact.
*/
on_is_compact(val) {
if (val) {
this.elem.removeClass('full');
@@ -99,6 +143,10 @@ export class LayoutAware extends ts.Events {
}
}

/**
* Handles changes in the super compact state of the main area layout.
* @param {boolean} val Indicates if the main area layout is super compact.
*/
on_is_super_compact(val) {
if (val) {
this.elem.addClass('super-compact');
@@ -107,10 +155,19 @@ export class LayoutAware extends ts.Events {
}
}

/**
* Handles changes on the sidebar resize event.
* @param {} inst
* @param {Object} sidebar
*/
on_sidebar_resize(inst, sidebar) {
this.is_sidebar_collapsed = sidebar.collapsed;
}

/**
* Handles changes in the sidebar collapsed state.
* @param {boolean} val
*/
on_is_sidebar_collapsed(val) {
// ...
}
66 changes: 54 additions & 12 deletions js/src/mainmenu.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import $ from 'jquery';
import ts from 'treibstoff';
import {LayoutAware} from './layout.js';
import { LayoutAware } from './layout.js';

/**
* Class to manage the main menu of the application.
* @extends LayoutAware
*/
export class MainMenu extends LayoutAware {

/**
* Initializes the MainMenu instance.
* @param {Element} context
*/
static initialize(context) {
const elem = ts.query_elem('#mainmenu', context);
if (!elem) {
@@ -12,10 +20,12 @@ export class MainMenu extends LayoutAware {
new MainMenu(elem);
}

/**
* @param {Element} elem
*/
constructor(elem) {
super(elem);
this.elem = elem;
this.height = this.elem.outerHeight();
this.scrollbar = elem.data('scrollbar');
this.elems = $('.nav-link.dropdown-toggle', elem);
this.open_dropdown = null;
@@ -26,6 +36,18 @@ export class MainMenu extends LayoutAware {
this.scrollbar.on('on_position', this.hide_dropdowns);
}

/**
* Returns the main menu element's outer height.
*/
get height() {
return this.elem.outerHeight(true);
}

/**
* Handles changes in the sidebar resize event.
* @param {} inst
* @param {Object} sidebar
*/
on_sidebar_resize(inst, sidebar) {
super.on_sidebar_resize(inst, sidebar);
// defer to next frame to ensure elements have correct dimensions
@@ -34,6 +56,11 @@ export class MainMenu extends LayoutAware {
});
}

/**
* Handles changes in the compact state of the main menu.
* Binds modified dropdown behavior to bootstrap dropdowns.
* @param {boolean} val
*/
on_is_compact(val) {
this.hide_dropdowns();

@@ -46,42 +73,57 @@ export class MainMenu extends LayoutAware {
}
}

/**
* Handles the event when a dropdown is shown on desktop.
* Sets the dropdown position manually due to position being set as
* 'static' in css (to avoid dropdowns being cut by overflow: hidden)
* @param {Event} evt
*/
on_show_dropdown_desktop(evt) {
const el = evt.target;
this.open_dropdown = el;

// prevent element being cut by scrollbar while open
const dropdown = $(el).siblings('ul.dropdown-menu');
dropdown.css({
top: `${this.height}px`,
top: `${this.height - 1}px`, // remove border from position
left: `${$(el).offset().left}px`
});
}

/**
* Handles the event when a dropdown is hidden on desktop.
* @param {Event} evt
*/
on_hide_dropdown_desktop(evt) {
const el = evt.target;
// return if the click that closes the dropdown opens another dropdown
if (this.open_dropdown !== el) {
return;
}
this.elem.css('height', '100%');
this.open_dropdown = null;
}

/**
* Binds the dropdown events for desktop view.
*/
bind_dropdowns_desktop() {
this.elems.each((i, el) => {
$(el).on('shown.bs.dropdown', this.on_show_dropdown_desktop);
$(el).on('hidden.bs.dropdown', this.on_hide_dropdown_desktop);
});
// this.elems.on(...) and this.elems.each(...on(...)) are deprecated in jquery 4.0.0-beta.2
this.elem.on('shown.bs.dropdown', '.nav-link.dropdown-toggle', this.on_show_dropdown_desktop);
this.elem.on('hidden.bs.dropdown', '.nav-link.dropdown-toggle', this.on_hide_dropdown_desktop);
}

/**
* Unbinds the dropdown events for mobile view.
*/
bind_dropdowns_mobile() {
this.elems.each((i, el) => {
$(el).off('shown.bs.dropdown', this.on_show_dropdown_desktop);
$(el).off('hidden.bs.dropdown', this.on_hide_dropdown_desktop);
});
this.elem.off('shown.bs.dropdown', '.nav-link.dropdown-toggle', this.on_show_dropdown_desktop);
this.elem.off('hidden.bs.dropdown', '.nav-link.dropdown-toggle', this.on_hide_dropdown_desktop);
}

/**
* Hides all dropdowns in the main menu.
*/
hide_dropdowns() {
this.elems.each((i, el) => {
$(el).dropdown('hide');
58 changes: 51 additions & 7 deletions js/src/sidebar.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import $ from 'jquery';
import ts from 'treibstoff';
import {global_events} from './globals.js';
import { global_events } from './globals.js';

/**
* Class to manage the sidebar of the application.
* @extends ts.Motion
*/
export class Sidebar extends ts.Motion {

/**
* Initializes the Sidebar instance.
* @param {Element} context
*/
static initialize(context) {
const elem = ts.query_elem('#sidebar_left', context);
if (!elem) {
@@ -12,6 +20,10 @@ export class Sidebar extends ts.Motion {
new Sidebar(elem);
}

/**
* Creates an instance of the Sidebar.
* @param {Element} elem
*/
constructor(elem) {
super();
this.elem = elem;
@@ -26,7 +38,7 @@ export class Sidebar extends ts.Motion {
elem.css(
'min-width',
`calc(${logo_width}px + ${pad_left} + ${pad_right})`
)
);

this.on_click = this.on_click.bind(this);
const collapse_elem = ts.query_elem('#sidebar_collapse', elem);
@@ -39,22 +51,37 @@ export class Sidebar extends ts.Motion {
$(window).on('resize', this.responsive_toggle);
this.responsive_toggle();

// enable scroll to refresh page on mobile devices
// Enable scroll to refresh page on mobile devices
$('html, body').css('overscroll-behavior', 'auto');
}

/**
* Gets the current width of the sidebar from local storage.
* @returns {number}
*/
get sidebar_width() {
return localStorage.getItem('cone-app-sidebar-width') || 300;
}

/**
* Sets the width of the sidebar in local storage.
* @param {number} width
*/
set sidebar_width(width) {
localStorage.setItem('cone-app-sidebar-width', width);
}

/**
* Checks if the sidebar is collapsed.
* @returns {boolean}
*/
get collapsed() {
return (this.elem.outerWidth() <= 0);
return this.elem.outerWidth() <= 0;
}

/**
* Toggles the sidebar's responsive state and css class based on its width.
*/
responsive_toggle() {
if (this.collapsed) {
this.elem.removeClass('responsive-expanded');
@@ -70,24 +97,34 @@ export class Sidebar extends ts.Motion {
}
}

/**
* Collapses the sidebar and triggers the resize event.
*/
collapse() {
// enable scroll to refresh page on mobile devices
// Enable scroll to refresh page on mobile devices
$('html, body').css('overscroll-behavior', 'auto');
this.elem
.removeClass('expanded')
.addClass('collapsed');
global_events.trigger('on_sidebar_resize', this);
}

/**
* Expands the sidebar and triggers the resize event.
*/
expand() {
// disable scroll to refresh page on mobile devices
// Disable scroll to refresh page on mobile devices
$('html, body').css('overscroll-behavior', 'none');
this.elem
.removeClass('collapsed')
.addClass('expanded');
global_events.trigger('on_sidebar_resize', this);
}

/**
* Handles click events to toggle the sidebar's collapsed state.
* @param {Event} evt
*/
on_click(evt) {
if (this.collapsed) {
this.expand();
@@ -96,16 +133,23 @@ export class Sidebar extends ts.Motion {
}
}

/**
* Handles the mouse move event to adjust the sidebar width.
* @param {Event} evt
*/
move(evt) {
this.scrollbar.pointer_events = false;
if (evt.pageX <= 115) {
evt.pageX = 115;
evt.pageX = 115; // Prevent sidebar from collapsing too much
}
this.sidebar_width = parseInt(evt.pageX);
this.elem.css('width', this.sidebar_width);
global_events.trigger('on_sidebar_resize', this);
}

/**
* Finalizes the sidebar resizing on mouse up.
*/
up() {
this.scrollbar.pointer_events = true;
global_events.trigger('on_sidebar_resize', this);

0 comments on commit ca9631b

Please sign in to comment.