UNPKG

smoosic

Version:

<sub>[Github site](https://github.com/Smoosic/smoosic) | [source documentation](https://smoosic.github.io/Smoosic/release/docs/modules.html) | [change notes](https://aarondavidnewman.github.io/Smoosic/changes.html) | [application](https://smoosic.github.i

346 lines (326 loc) 9.8 kB
// [Smoosic](https://github.com/AaronDavidNewman/Smoosic) // Copyright (c) Aaron David Newman 2021. declare var $: any; /** * returns an object that lets you build a DOM in a somewhat readable way. * * ## Usage * ``` javascript * var b = buildDom; * var r = * b('tr').classes('jsSharingMember').data('entitykey', key).data('name', name).data('entitytype', entityType).append( * b('td').classes('noSideBorderRight').append( * ... * $(parent).append(r.dom()); * ``` * Don't forget the '.dom()' ! That is the actual jquery element object * @internal * @returns **/ export class DomBuilder { e: any; constructor(el: any) { this.e = $('<' + el + '/>'); } classes(cl: any) { $(this.e).addClass(cl); return this; } html(value: any) { $(this.e).html(value); return this; } data(name: string, value: string) { $(this.e).attr('data-' + name, value); return this; } attr(name: string, value: string) { $(this.e).attr(name, value); return this; } prop(name: string, value: boolean) { $(this.e).prop(name, value); return this; } css(name: string, value: string) { $(this.e).css(name, value); return this; } append(el: any) { $(this.e).append(el.e); return this; } text(tx: any) { $(this.e).append(document.createTextNode(tx)); return this; } dom() { return this.e; } } export function buildDom(e: any) { return new DomBuilder(e); } export function focusableElements(): string[] { return ['a', 'input', 'select', 'textarea', 'button', 'li[tabindex]', 'div[tabindex]']; } export function addFileLink(filename: string, txt: any, parent: any, mimeType: string = 'application/octet-stream') { var anchor = $('<a></a>'); var url = URL.createObjectURL(new Blob([txt], { type: mimeType })); $(anchor).attr('href', url); $(anchor).attr('download', filename); $(anchor).text('save'); $(parent).html(''); $(parent).append(anchor); } /** * @internal */ export class InputTrapper { selector: any; parent: any; id: any; parentId: any; modalInputs: any[]; disabledInputs: any[]; siblingInputs: any[]; constructor(selector: any) { this.selector = selector; this.modalInputs = []; this.disabledInputs = []; this.siblingInputs = []; this.parent = $(this.selector); this.id = $(this.parent).attr('id'); this.parentId = $(this.parent).parent().attr('id'); var idstr = Math.round(Math.random() * (999999 - 1) + 1); if (!this.id) { $(this.parent).attr('id', idstr + '-element'); this.id = $(this.parent).attr('id'); } if (!this.parentId) { $(this.parent).parent().attr('id', idstr + '-parent'); this.parentId = $(this.parent).parent().attr('id'); } } trap(this: any) { // aria-hide peers of dialog and peers of parent that are not the parent. var peers = $(this.parent).parent().children().toArray(); peers.forEach((node: any) => { var ptag: any = $(node)[0].tagName; if (ptag === 'SCRIPT' || ptag === 'LINK' || ptag === 'STYLE') { ; } else if ($(node).attr('id') === this.parentId || $(node).attr('id') === this.id || $(node).hasClass('helpDialog')) { // help dialog can be shown with modal dialog ; } else { var hidden = $(node).attr('aria-hidden'); if (!hidden || hidden != 'true') { $(node).attr('aria-hidden', 'true'); this.siblingInputs.push(node); } } }); focusableElements().forEach((etype) => { var elements = $(etype).toArray(); elements.forEach((element: any) => { var tagName = $(element)[0].tagName; if ($(element).attr('id') === this.id) { ; } else if ($(element).closest('.helpDialog').length) { ; } else if ($(element).prop('disabled')) { ; } else if ($(element).hasClass('hide')) { ; } else if ($(element).closest(this.selector).length) { // inside this.modalInputs.push(element); } else if ((tagName === 'A' || tagName === 'DIV' || tagName === 'LI') && $(element).attr('tabIndex') === '-1') { ; } else { this.disabledInputs.push(element); if (tagName === 'A' || tagName === 'DIV' || tagName === 'LI') { $(element).attr('tabIndex', '-1'); } else { $(element).prop('disabled', true); } } }); }); } close() { this.disabledInputs.forEach(function (element: any) { var tagName = $(element)[0].tagName; if (tagName === 'A' || tagName === 'DIV' || tagName === 'LI') { $(element).attr('tabIndex', '0'); } else { $(element).prop('disabled', false); } }); this.siblingInputs.forEach((el: any) => { $(el).removeAttr('aria-hidden'); }); } } export function closeDialogPromise(): Promise<void> { return new Promise<void>((resolve) => { $('body').off('dialogDismiss').on('dialogDismiss', function () { resolve(); }); }); } /** * Extract an HTMLElement from a Jquery id, DOM element ID, or HTMLELement. If * an HTMLElement can't be created, return null * @param selector * @returns HTMLElement */ export function getDomContainer(selector: HTMLElement | string): HTMLElement | undefined { if (typeof(selector) === 'string') { if (selector[0] === '#') { const el: any = $(selector)[0]; if (!(el instanceof HTMLElement)) { return undefined; } return el; } else { const el = document.getElementById(selector); if (!el) { return undefined; } return el; } } else if (selector instanceof HTMLElement) { return selector; } else { return undefined; } } /** * Create a top-level HTML element for modal containers - dialogs etc. * from a jquery selector, or just return same if it exists * @param selector * @returns */ export function createTopDomContainer(selector: string | HTMLElement, elementType?: string): HTMLElement { const container = $(selector); if (!elementType) { elementType = 'div'; } if (container.length > 0) { return container[0] as HTMLElement; } else { const ndiv = document.createElement(elementType); if (typeof(selector) === 'string') { const cl = (selector[0] === '.' || selector[0] === '#') ? selector.substring(1) : selector; $(ndiv).addClass(cl); if (selector[0] === '#') { $(ndiv).attr('id', selector.substring(1)); } } $('body').append(ndiv); return $(ndiv)[0] as HTMLElement; } } /** * * @param parameters * @returns */ export function draggable(parameters: any) { return new Draggable(parameters); } /** * @internal */ export class Draggable { parent: any; handle: any; animeClass: any; dragParent: any; domOffset: any; svg: any; width: number; height: number; lastX: number; lastY: number; cb: any; moveParent: boolean; dragging: boolean = false; constructor(parameters: any) { this.parent = parameters.parent; this.handle = parameters.handle; this.animeClass = parameters.animateDiv; this.dragParent = parameters.dragParent; // TODO: make '.dom-container' a part of the configuration this.domOffset = $('.dom-container').offset(); this.svg = parameters['svg']; this.width = $(this.parent).outerWidth(); this.height = $(this.parent).outerHeight(); this.lastX = $(this.handle).offset().left - this.domOffset.left; this.lastY = $(this.handle).offset().top - this.domOffset.top; this.cb = parameters.cb; this.moveParent = parameters.moveParent; var self = this; // $('.itemMenu input[name="itemTitle"]').css('width','60%'); $(this.handle) .off('mousedown').on('mousedown', function (e: any) { self.mousedown(e); }); $(document) .on('mousemove', function (e: any) { self.mousemove(e); }) .on('mouseup', function (e: any) { self.mouseup(e); }); } _animate(e: any) { this.lastX = e.clientX; this.lastY = e.clientY; $(this.animeClass).css('left', this.lastX - this.domOffset.left); $(this.animeClass).css('top', this.lastY - this.domOffset.top); if (this.dragParent) { $(this.parent).css('left', this.lastX + 'px'); $(this.parent).css('top', this.lastY + 'px'); } } mousedown(e: any) { if (!this.dragging) { $(this.animeClass).removeClass('hide'); $(this.animeClass).css('width', this.width); $(this.animeClass).css('height', this.height); } this.dragging = true; this._animate(e); } enddrag() { this.lastX = Math.max(this.lastX - this.domOffset.left, 0); this.lastY = Math.max(this.lastY - this.domOffset.top, 0); if (this.moveParent) { $(this.parent).css('left', this.lastX + 'px'); $(this.parent).css('top', this.lastY + 'px'); } $(this.animeClass).addClass('hide'); this.cb(this.lastX, this.lastY); } mouseup(e: any) { // stop resizing if (this.dragging) { this.dragging = false; this.lastX = e.clientX; this.lastY = e.clientY; this.enddrag(); } } mousemove(e: any) { // we don't want to do anything if we aren't resizing. if (!this.dragging) return; this._animate(e); } }