/** * @license * Copyright 2022 Superflow.dev * SPDX-License-Identifier: MIT */ import {LitElement, html, css, PropertyValueMap} from 'lit'; // import {customElement, query, queryAssignedElements, property} from 'lit/decorators.js'; // import {customElement, query, queryAssignedElements, property} from 'lit/decorators.js'; import {customElement, property, query} from 'lit/decorators.js'; // import {customElement, query, property} from 'lit/decorators.js'; // import Util from './util'; // import {LitElement, html, css} from 'lit'; // import {customElement} from 'lit/decorators.js'; /* Modes: View, Add, Edit, Delete, Admin DB: partitionKey, rangeKey, values */ /** * SfIMultitextarea element. * @fires renderComplete - When the list is populated * @fires valueChanged - When the value is changed * @property apiId - backend api id * @property label - input label * @property name - name of the input * @property mode - mode of operation * @property selectedId - id to preselect * @property selectedValue - callback function */ @customElement('sf-i-multitextarea') export class SfIMultitextarea extends LitElement { SCROLL_POS = 0; @query('.SfIMultitextareaC') _SfMultitextareaX: any; @property() disabled: boolean = false; @property() hint: string = ""; @property() showFields: number = 3; @property() fields!: string; getFields = () => { return JSON.parse(this.fields); } @property() values!: string; getValues = () => { try { let currValues : any = JSON.parse(/^".*"$/.test(this.values) ? this.values.replace(/\"/g, '') : this.values); for(var i = 0; i < this.getFields().length; i++) { if(currValues[this.getFields()[i]] == null) { currValues[this.getFields()[i]] = ""; } } return currValues; } catch (e: any) { let retValue: any = {}; for(var i = 0; i < this.getFields().length; i++) { retValue[this.getFields()[i]] = this.values; } return retValue; } } @property() flow: string = ""; @property() collapsed: boolean = true; @property() showCollapsed: boolean | null = null; static override styles = css` .SfIMultitextareaC { display: flex; align-items: center; } .flex-grow { flex-grow: 1; } .left-sticky { left: 0px; position: sticky; } .cursor { cursor: pointer; } .hint { font-size: 80%; color: #999; font-weight: 400; padding-left: 5px; } .collapse-content { font-size: 120%; color: gray !important; margin-left: 5px; margin-top: 2px; } .multitextarea-overwrite, .multitextarea-prev, .multitextarea-next { background: transparent; border: none; padding: 2px; color: gray } .multitextarea-input { border: none; padding: 5px; border-radius: 5px; background: white; box-shadow: inset 3px 3px 5px #bbbbbb, inset -5px -5px 8px #ffffff; border-top: solid 1px #e9c4d2; border-left: solid 1px #e9c4d2; border-bottom: solid 1px #e9c4d2; border-right: solid 1px #e9c4d2; transition: 0.3s; } .link { text-decoration: underline; cursor: pointer; } .gone { display: none } .overwrite-hide { display: none; } .overwrite-show { display: block; } .unfocused { width: 40px; font-size: 70%; } .unfocused-label { display: block; width: 40px; font-size: 80%; white-space: nowrap; overflow: hidden; text-transform: capitalize; color: #666; } .focused { width: 150px; } .focused-label { display: block; width: 100px; text-transform: capitalize; color: #666; } .loader-element { position: fixed; right: 10px; top: 10px; margin-left: 5px; } .td-head { text-transform: capitalize; } .td-body { padding: 5px; } .td-dark { background-color: #e9e9e9; } .td-highlight { background-color: black; color: white; } .td-light { background-color: #f6f6f6; } td { white-space: nowrap; } .align-start { align-items: flex-start; } .align-end { align-items: flex-end; } .align-center { align-items: center; } .lds-dual-ring { display: inline-block; width: 50px; height: 50px; } .lds-dual-ring:after { content: " "; display: block; width: 50px; height: 50px; margin: 0px; border-radius: 50%; border: 2px solid #fff; border-color: #888 #ddd #888 #ddd; background-color: white; animation: lds-dual-ring 0.8s linear infinite; } .lds-dual-ring-lg { display: inline-block; width: 30px; height: 30px; } .lds-dual-ring-lg:after { content: " "; display: block; width: 30px; height: 30px; margin: 0px; border-radius: 50%; border: 3px solid #fff; border-color: #888 #ddd #888 #ddd; animation: lds-dual-ring 0.8s linear infinite; } .div-row-error { display: flex; justify-content: center; position: fixed; position: fixed; top: 0px; right: 0px; margin-top: 20px; margin-right: 20px; display: none; align-items:center; background-color: white; border: dashed 1px red; padding: 20px; } .div-row-error-message { color: red; padding: 5px; background-color: white; text-align: center; } .div-row-success { display: flex; justify-content: center; position: fixed; top: 0px; right: 0px; margin-top: 20px; margin-right: 20px; display: none; align-items:center; background-color: white; border: dashed 1px green; padding: 20px; } .div-row-success-message { color: green; padding: 5px; background-color: white; text-align: center; } .d-flex { display: flex; } .flex-col { flex-direction: column; } .justify-center { justify-content: center; } .justify-between { justify-content: space-between; } .justify-end { justify-content: flex-end; } @keyframes lds-dual-ring { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .hide { display: none; } .lb { width: 5% } .rb { width: 5% } @media (orientation: landscape) { .lb { width: 30% } .rb { width: 30% } } .ml-5 { margin-left: 5px; } .mr-5 { margin-right: 5px; } .p-5 { padding: 5px; } `; getFieldsHtml = () => { var html = ''; const jsonFields = this.getFields(); html += '
'; html += '
'; if(this.showCollapsed != null && this.collapsed && this.collapsed != null && this.collapsed) { html += 'expand_content'; } else { if((this.SCROLL_POS) > 0) { html += ''; } var pos = 0; for(var i = this.SCROLL_POS; (i < jsonFields.length) && ((i - this.SCROLL_POS) < this.showFields); i++) { html += '
'; html += ''; html += '
'; html += ''; html += 'compare_arrows'; html += '
'; html += '
'; pos++; } if((this.SCROLL_POS + this.showFields) < this.getFields().length) { html += ''; } html += '
'; if(this.hint.length > 0) { html += ('
'+this.hint+'
'); } } if((this.showCollapsed != null || this.showCollapsed) && !this.collapsed) { html += '
arrow_circle_up
'; } html += '
'; return html; } loadFieldsHtml = () => { this._SfMultitextareaX.innerHTML = this.getFieldsHtml(); } getFilled = () => { let filled: boolean = false; for(var i = 0; i < Object.keys(this.getValues()).length; i++) { if(this.getValues()[Object.keys(this.getValues())[i]] != "") { filled = true; break; } } return filled; } initListeners = () => { const inputs = this._SfMultitextareaX.querySelectorAll('textarea'); if(inputs.length > 0) { for(var i = 0; i < inputs.length; i++) { (inputs[i] as HTMLTextAreaElement).addEventListener('focus', (e: any) => { console.log(e.target); const input = e.target as HTMLInputElement; const label = input.parentElement?.parentElement?.firstChild as HTMLLabelElement; const spanOverwrite = input.nextSibling as HTMLLabelElement; input.classList.remove('unfocused'); input.classList.add('focused'); label.classList.remove('unfocused-label'); label.classList.add('focused-label'); spanOverwrite.classList.remove('overwrite-hide'); spanOverwrite.classList.add('overwrite-show'); }); (inputs[i] as HTMLTextAreaElement).addEventListener('focusout', (e: any) => { console.log(e.target); const input = e.target as HTMLInputElement; const label = input.parentElement?.parentElement?.firstChild as HTMLLabelElement; const spanOverwrite = input.nextSibling as HTMLLabelElement; input.classList.remove('focused'); input.classList.add('unfocused'); label.classList.remove('focused-label'); label.classList.add('unfocused-label'); spanOverwrite.classList.remove('overwrite-show'); spanOverwrite.classList.add('overwrite-hide'); }); (inputs[i] as HTMLTextAreaElement).addEventListener('keyup', (e: any) => { console.log(e.target.id); const index = e.target.id.split('-')[2]; let tempValues: any = this.getValues(); tempValues[this.getFields()[index]] = e.target.value; this.values = JSON.stringify(tempValues); }); } } const overwrite = this._SfMultitextareaX.querySelectorAll('.multitextarea-overwrite'); if(overwrite.length > 0) { for(var i = 0; i < overwrite.length; i++) { (overwrite[i] as HTMLTextAreaElement).addEventListener('mousedown', (e: any) => { const tempValues = this.getValues(); const index = e.target.id.split('-')[2]; console.log('mousedown', tempValues, index); const value = inputs[index - this.SCROLL_POS].value; console.log('mousedown', inputs[index - this.SCROLL_POS]); for(var i = 0; i < this.getFields().length; i++) { const field = this.getFields()[i]; console.log(field, value); tempValues[field] = value; } this.values = JSON.stringify(tempValues); console.log(this.values); this.loadFieldsHtml(); this.initListeners(); }); } } const buttonPrev = this._SfMultitextareaX.querySelector('.multitextarea-prev') as HTMLButtonElement; if(buttonPrev != null) { buttonPrev?.addEventListener('click', () => { for(var i = 0; i < this.showFields; i++) { if(this.SCROLL_POS > 0) { this.SCROLL_POS--; } } console.log('SCROLL_POS', this.SCROLL_POS); this.loadFieldsHtml(); this.initListeners(); }) } const buttonNext = this._SfMultitextareaX.querySelector('.multitextarea-next') as HTMLButtonElement; if(buttonNext != null) { buttonNext?.addEventListener('click', () => { for(var i = 0; i < this.showFields; i++) { if(this.SCROLL_POS < (this.getFields().length - 1)) { this.SCROLL_POS++; } } console.log('SCROLL_POS', this.SCROLL_POS); this.loadFieldsHtml(); this.initListeners(); }) } const expandContent = this._SfMultitextareaX.querySelector('.expand-content') as HTMLSpanElement; if(expandContent != null) { expandContent.addEventListener('click', () => { this.collapsed = false; this.loadFieldsHtml(); this.initListeners(); }) } const collapseContent = this._SfMultitextareaX.querySelector('.collapse-content') as HTMLSpanElement; if(collapseContent != null) { collapseContent.addEventListener('click', () => { this.collapsed = true; this.loadFieldsHtml(); this.initListeners(); }) } } loadMode = async () => { this.loadFieldsHtml(); this.initListeners(); } constructor() { super(); } protected override firstUpdated(_changedProperties: PropertyValueMap | Map): void { this.loadMode(); } override connectedCallback() { super.connectedCallback() } override render() { return html`
`; } } declare global { interface HTMLElementTagNameMap { 'sf-i-multitextarea': SfIMultitextarea; } }