@exadel/esl
Version:
Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components
194 lines (193 loc) • 7.26 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var ESLFootnotes_1;
import { ExportNs } from '../../esl-utils/environment/export-ns';
import { bind, memoize, attr, listen, prop } from '../../esl-utils/decorators';
import { debounce } from '../../esl-utils/async/debounce';
import { ESLBaseElement } from '../../esl-base-element/core';
import { ESLEventUtils } from '../../esl-utils/dom/events';
import { ENTER, SPACE } from '../../esl-utils/dom/keys';
import { sequentialUID } from '../../esl-utils/misc/uid';
import { compileFootnotesGroupedList, compileFootnotesNongroupedList, sortFootnotes } from './esl-footnotes-data';
let ESLFootnotes = ESLFootnotes_1 = class ESLFootnotes extends ESLBaseElement {
constructor() {
super(...arguments);
this._notes = [];
this.deferredOnUpdate = debounce(() => this._onUpdate(), 150);
}
/** Scope element */
get scopeEl() {
return this.$$find(this.scopeTarget);
}
/** Notes that are allowed to be processed by footnotes */
get notes() {
return this._notes.filter((note) => note.allowFootnotes);
}
/** List of notes to show */
get footnotesList() {
this.reindex();
return this.grouping !== 'enable'
? compileFootnotesNongroupedList(this._notes)
: compileFootnotesGroupedList(this._notes);
}
connectedCallback() {
super.connectedCallback();
if (!this.id) {
this.id = sequentialUID(this.baseTagName, this.baseTagName + '-');
}
this._notifyNotes();
}
disconnectedCallback() {
super.disconnectedCallback();
this._notes.forEach((el) => el.unlink());
this._notes = [];
}
/** Adds the note to the footnotes list */
linkNote(note) {
if (this._notes.includes(note))
return;
this._notes.push(note);
const index = +sequentialUID(ESLFootnotes_1.is, '');
note.link(this, index);
}
/** Reindexes the list of notes */
reindex() {
this._sortNotes();
this.notes.forEach((note, index) => note.index = index + 1);
}
/** Removes the note from the footnotes list */
unlinkNote(note) {
this._notes = this._notes.filter((el) => el !== note);
this.deferredOnUpdate();
}
/** Updates the content of footnotes */
update() {
this.deferredOnUpdate();
}
/** Sorts list of notes */
_sortNotes() {
this._notes = sortFootnotes(this._notes);
}
/** Builds content of footnotes */
buildItems() {
const items = this.footnotesList.map((footnote) => this.buildItem(footnote)).join('');
return `<ul class="esl-footnotes-items">${items}</ul>`;
}
/** Builds one item from footnotes list */
buildItem(footnote) {
const item = `${this.buildItemIndex(footnote)}${this.buildItemText(footnote)}${this.buildItemBack(footnote)}`;
return `<li class="esl-footnotes-item" data-order="${footnote.index}">${item}</li>`;
}
/** Builds item index */
buildItemIndex(footnote) {
return `<span class="esl-footnotes-index">${footnote.renderedIndex.map(this.buildWrappedItemIndex).join(', ')}</span>`;
}
/** Builds item index wrapped with span related to esl-note by id */
buildWrappedItemIndex(index) {
return `<span id="${this.id}-${index}">${index}</span>`;
}
/** Builds item text */
buildItemText(footnote) {
return `<span class="esl-footnotes-text">${footnote.text}</span>`;
}
/** Builds item back-to-note button */
buildItemBack(footnote) {
return `<span class="esl-footnotes-back-to-note" tabindex="0" title="${this.backToNoteLabel}"></span>`;
}
/** Actions on update footnotes */
_onUpdate() {
this.innerHTML = this.buildItems();
}
/** Handles `response` event from note */
_onNoteSubscribe(e) {
const note = e.target;
this.linkNote(note);
this.deferredOnUpdate();
e.stopImmediatePropagation();
}
/** Handles `click` event */
_onItemClick(e) {
var _a;
const target = e.target;
const orderAttr = (_a = target.closest('.esl-footnotes-item')) === null || _a === void 0 ? void 0 : _a.getAttribute('data-order');
const order = orderAttr === null || orderAttr === void 0 ? void 0 : orderAttr.split(',').map((item) => +item);
order && this._onBackToNote(order);
e.preventDefault();
e.stopPropagation();
}
/** Handles `keydown` event */
_onKeydown(event) {
if ([ENTER, SPACE].includes(event.key))
this._onItemClick(event);
}
/** Actions on back-to-note click */
_onBackToNote(order) {
const index = order[order.length - 1];
this.notes.forEach((note) => {
note.highlight(order.includes(note.index));
if (note.index === index) {
note.activate();
}
});
}
/** Turns off highlight for notes with the same text */
turnOffHighlight(note) {
this._notes
.filter((item) => note.html === item.html)
.forEach((item) => item.highlight(false));
}
/**
* Sends a request to all notes, expecting to get a response from
* the unlinked ones and link up with them */
_notifyNotes() {
ESLEventUtils.dispatch(this, this.FOOTNOTE_REQUEST_EVENT);
}
};
ESLFootnotes.is = 'esl-footnotes';
__decorate([
prop('esl:footnotes:request')
], ESLFootnotes.prototype, "FOOTNOTE_REQUEST_EVENT", void 0);
__decorate([
prop('esl:footnotes:response')
], ESLFootnotes.prototype, "FOOTNOTE_RESPONSE_EVENT", void 0);
__decorate([
attr({ defaultValue: '::parent' })
], ESLFootnotes.prototype, "scopeTarget", void 0);
__decorate([
attr({ defaultValue: 'enable' })
], ESLFootnotes.prototype, "grouping", void 0);
__decorate([
attr({ defaultValue: 'Back to note' })
], ESLFootnotes.prototype, "backToNoteLabel", void 0);
__decorate([
memoize()
], ESLFootnotes.prototype, "scopeEl", null);
__decorate([
bind
], ESLFootnotes.prototype, "buildWrappedItemIndex", null);
__decorate([
bind
], ESLFootnotes.prototype, "_onUpdate", null);
__decorate([
listen({
event: (el) => el.FOOTNOTE_RESPONSE_EVENT,
target: (el) => el.scopeEl
})
], ESLFootnotes.prototype, "_onNoteSubscribe", null);
__decorate([
listen({
event: 'click',
selector: '.esl-footnotes-back-to-note'
})
], ESLFootnotes.prototype, "_onItemClick", null);
__decorate([
listen('keydown')
], ESLFootnotes.prototype, "_onKeydown", null);
ESLFootnotes = ESLFootnotes_1 = __decorate([
ExportNs('Footnotes')
], ESLFootnotes);
export { ESLFootnotes };