Skip to content

Commit

Permalink
Merge pull request #382 from exadel-inc/feature/footnotes-grouping
Browse files Browse the repository at this point in the history
feat(esl-footnotes): add a grouping of footnotes with non-unique text
  • Loading branch information
dshovchko authored Aug 13, 2021
2 parents f3487d5 + b15c87e commit b14d28f
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 16 deletions.
8 changes: 4 additions & 4 deletions pages/views/drafts/esl-footnotes.njk
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ tags: drafts

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore <esl-note>et dolore magna</esl-note> aliqua. Donec massa sapien faucibus et molestie ac. Mi sit amet mauris commodo quis imperdiet massa. Viverra nibh cras pulvinar mattis nunc sed blandit. In nisl nisi scelerisque eu. Vel turpis nunc eget lorem dolor sed. Nisl pretium fusce id velit. Quam id leo in vitae turpis massa sed. Mauris sit amet <esl-note>massa vitae tortor</esl-note>. Ut aliquam purus sit amet luctus venenatis lectus magna.</p>
<p>Dolor magna eget est lorem ipsum dolor sit amet. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. In vitae turpis massa sed elementum tempus egestas sed. Dui accumsan sit amet nulla facilisi morbi tempus. Diam quam nulla porttitor massa. Aliquet enim tortor at auctor urna nunc id cursus metus. Volutpat maecenas volutpat blandit aliquam etiam erat. Est pellentesque elit <esl-note>ullamcorper dignissim cras</esl-note> tincidunt lobortis feugiat. Sagittis purus sit amet volutpat consequat. Sit amet porttitor eget dolor morbi. Et netus et malesuada fames ac turpis. Egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate. Pulvinar pellentesque habitant morbi tristique senectus et netus et malesuada. Sit amet cursus sit amet dictum. Potenti nullam ac tortor vitae purus faucibus ornare. In nulla posuere sollicitudin aliquam ultrices sagittis orci. Blandit volutpat maecenas volutpat blandit aliquam etiam erat. Aliquam ultrices sagittis orci a. Sit amet consectetur adipiscing elit pellentesque habitant.</p>
<p>Mattis molestie a iaculis at erat pellentesque adipiscing commodo. Massa tincidunt nunc pulvinar sapien et ligula. Lectus urna duis convallis convallis tellus id interdum. Elit sed vulputate mi sit. Adipiscing commodo elit at imperdiet dui accumsan sit amet nulla. Lacus viverra vitae congue eu consequat ac felis donec et. Eget mauris pharetra et ultrices neque ornare <esl-note>aenean euismod elementum</esl-note>. Mattis aliquam faucibus purus in massa tempor nec feugiat nisl. Est ante in nibh <esl-note>mauris cursus mattis molestie</esl-note>. Velit dignissim sodales ut eu. Quam lacus suspendisse faucibus interdum posuere. Magna fringilla urna porttitor rhoncus dolor purus non enim praesent. Vulputate enim nulla aliquet porttitor. Facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum dui. Arcu non sodales neque sodales ut etiam. Adipiscing enim eu turpis egestas pretium aenean pharetra magna ac. A scelerisque purus semper eget duis at tellus at urna. Feugiat nibh sed pulvinar proin gravida hendrerit lectus. Arcu bibendum at varius vel pharetra vel turpis.</p>
<esl-footnotes></esl-footnotes>
<p>Mattis molestie a iaculis at erat pellentesque adipiscing commodo. Massa tincidunt nunc pulvinar sapien et ligula. Lectus urna duis convallis convallis tellus id interdum. Elit sed vulputate mi sit. Adipiscing commodo elit at imperdiet dui accumsan sit amet nulla. Lacus viverra vitae congue eu consequat ac felis donec et. Eget mauris pharetra et ultrices neque ornare <esl-note>aenean euismod elementum</esl-note>. Mattis aliquam faucibus purus in massa tempor nec feugiat nisl. Est ante in nibh <esl-note>mauris cursus mattis molestie</esl-note>. Velit dignissim sodales ut eu. Quam lacus suspendisse faucibus interdum posuere. Magna fringilla urna porttitor rhoncus dolor purus non enim praesent. Vulputate enim nulla aliquet porttitor. Facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum dui. Arcu non sodales neque sodales ut etiam. Adipiscing enim eu turpis egestas pretium aenean pharetra magna ac. A scelerisque purus semper eget duis at tellus at urna. Feugiat nibh sed pulvinar proin gravida hendrerit lectus. Arcu bibendum at varius <esl-note>et dolore magna</esl-note> vel pharetra vel turpis.</p>
<esl-footnotes grouping="disable"></esl-footnotes>

</div>

Expand All @@ -35,7 +35,7 @@ tags: drafts
<esl-footnotes></esl-footnotes>
</div>
<div class="col-4">
<p>Dolor magna eget est lorem ipsum dolor sit amet. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. In vitae turpis massa sed elementum tempus egestas sed. Dui accumsan sit amet nulla facilisi morbi tempus. Diam quam nulla porttitor massa. Aliquet enim tortor at auctor urna nunc id cursus metus. Volutpat maecenas volutpat blandit aliquam etiam erat. Est pellentesque elit <esl-note>ullamcorper dignissim cras</esl-note> tincidunt lobortis feugiat. Sagittis purus sit amet volutpat consequat. Sit amet porttitor eget dolor morbi. Et netus et malesuada fames ac turpis. Egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate. Pulvinar pellentesque habitant morbi tristique senectus et netus et malesuada. Sit amet cursus sit amet dictum. Potenti nullam ac tortor vitae purus faucibus ornare. In nulla posuere sollicitudin aliquam ultrices sagittis orci. Blandit volutpat maecenas volutpat blandit aliquam etiam erat. Aliquam ultrices sagittis orci a. Sit amet consectetur adipiscing elit pellentesque habitant.</p>
<p>Dolor magna eget est lorem ipsum dolor sit amet. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. In vitae turpis massa sed elementum tempus egestas sed. Dui accumsan sit amet nulla facilisi morbi tempus. Diam quam nulla porttitor massa. Aliquet enim tortor at auctor urna nunc id cursus metus. Volutpat maecenas volutpat blandit aliquam etiam erat. Est pellentesque elit <esl-note>ullamcorper dignissim cras</esl-note> tincidunt lobortis feugiat. Sagittis purus sit amet volutpat consequat. Sit amet porttitor eget dolor morbi. Et netus et malesuada fames ac turpis. Egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate. Pulvinar pellentesque habitant morbi tristique senectus et netus et malesuada. Sit amet cursus sit amet dictum. Potenti nullam ac tortor vitae purus faucibus ornare. In nulla posuere sollicitudin aliquam ultrices sagittis orci. Blandit volutpat maecenas volutpat blandit aliquam etiam erat. Aliquam ultrices sagittis orci a<esl-note>et dolore magna</esl-note>. Sit amet consectetur adipiscing elit pellentesque habitant.</p>
</div>
<div class="col-4">
<p>Mattis molestie a iaculis at erat pellentesque adipiscing commodo. Massa tincidunt nunc pulvinar sapien et ligula. Lectus urna duis convallis convallis tellus id interdum. Elit sed vulputate mi sit. Adipiscing commodo elit at imperdiet dui accumsan sit amet nulla. Lacus viverra vitae congue eu consequat ac felis donec et. Eget mauris pharetra et ultrices neque ornare <esl-note>aenean euismod elementum</esl-note>. Mattis aliquam faucibus purus in massa tempor nec feugiat nisl. Est ante in nibh <esl-note>mauris cursus mattis molestie</esl-note>. Velit dignissim sodales ut eu. Quam lacus suspendisse faucibus interdum posuere. Magna fringilla urna porttitor rhoncus dolor purus non enim praesent. Vulputate enim nulla aliquet porttitor. Facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum dui. Arcu non sodales neque sodales ut etiam. Adipiscing enim eu turpis egestas pretium aenean pharetra magna ac. A scelerisque purus semper eget duis at tellus at urna. Feugiat nibh sed pulvinar proin gravida hendrerit lectus. Arcu bibendum at varius vel pharetra vel turpis.</p>
Expand All @@ -46,7 +46,7 @@ tags: drafts
<p>Ullamcorper a lacus vestibulum sed arcu. Egestas tellus rutrum tellus pellentesque. Egestas diam in arcu <esl-note>cursus</esl-note>. Diam volutpat commodo sed egestas. Sit amet justo donec enim diam vulputate ut pharetra. Facilisis mauris sit amet massa vitae tortor condimentum lacinia. Fames ac turpis egestas integer eget. Id volutpat lacus laoreet non curabitur gravida. Orci phasellus egestas tellus rutrum tellus pellentesque eu. At risus viverra adipiscing at in tellus integer feugiat. Semper quis lectus nulla at. Massa id neque aliquam vestibulum morbi. Eget nunc lobortis mattis aliquam faucibus purus in. Urna porttitor rhoncus dolor purus non enim praesent elementum. Amet consectetur adipiscing elit pellentesque habitant morbi. Ullamcorper malesuada proin libero nunc consequat interdum varius sit. Ridiculus mus mauris vitae ultricies leo integer malesuada nunc. At varius vel pharetra vel turpis nunc eget.</p>
</div>
<div class="col-6">
<p>Lobortis elementum nibh tellus molestie nunc non. Tellus orci ac auctor augue. Orci nulla pellentesque dignissim enim sit amet. Massa tincidunt dui ut ornare lectus sit amet est placerat. Nisl pretium fusce id velit ut tortor pretium viverra. Porttitor massa id neque aliquam. Pulvinar proin gravida hendrerit lectus. Gravida neque convallis a cras. Urna nunc id cursus metus aliquam eleifend mi in nulla. Eu turpis egestas pretium aenean pharetra magna ac placerat vestibulum. Sed odio morbi quis commodo odio aenean. Molestie ac feugiat sed lectus vestibulum. Consequat semper viverra nam libero justo laoreet. Et netus et malesuada fames ac turpis egestas integer eget. Commodo nulla facilisi nullam vehicula ipsum a arcu cursus. Molestie at elementum eu facilisis. Sit amet consectetur adipiscing elit ut. Fermentum iaculis eu non diam phasellus vestibulum lorem sed.</p>
<p>Lobortis elementum nibh tellus molestie nunc non. Tellus orci ac auctor augue. Orci nulla pellentesque dignissim enim sit amet. Massa tincidunt dui ut ornare lectus sit amet est placerat. Nisl pretium fusce id velit ut tortor pretium viverra. Porttitor massa id neque aliquam. Pulvinar proin gravida hendrerit lectus. Gravida neque convallis a cras. Urna nunc id cursus metus aliquam eleifend mi in nulla. Eu turpis egestas pretium aenean pharetra magna ac placerat vestibulum. Sed odio morbi quis commodo odio aenean. Molestie ac feugiat sed lectus vestibulum. Consequat semper viverra nam libero justo laoreet. Et netus et malesuada fames ac turpis egestas integer eget. Commodo nulla facilisi nullam vehicula ipsum a arcu cursus. Molestie at elementum eu facilisis. Sit amet consectetur adipiscing elit ut. Fermentum iaculis <esl-note>et dolore magna</esl-note> eu non diam phasellus vestibulum lorem sed.</p>
</div>
</div>
<div class="row">
Expand Down
32 changes: 32 additions & 0 deletions src/modules/esl-footnotes/core/esl-footnotes-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type {ESLNote} from './esl-note';

export interface FootnotesItem {
index: string;
text: string;
}

/* Convert notes list to footnotes items list */
function convertNotesToFootnotesList(notes: ESLNote[]): FootnotesItem[] {
return notes.map(({index, html}) => ({
index: `${index}`,
text: html
}));
}

/* Compile footnotes non-grouped list */
export function compileFootnotesNongroupedList(notes: ESLNote[]): FootnotesItem[] {
return convertNotesToFootnotesList(notes);
}

/* Compile footnotes grouped list */
export function compileFootnotesGroupedList(notes: ESLNote[]): FootnotesItem[] {
const map = new Map();
convertNotesToFootnotesList(notes).forEach(({index, text}) => {
map.set(text, map.has(text) ? `${map.get(text)}, ${index}` : index);
});
return Array.from(map)
.reduce(
(list,[text, index]) => [...list, {index, text}],
[]
);
}
51 changes: 39 additions & 12 deletions src/modules/esl-footnotes/core/esl-footnotes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import {memoize} from '../../esl-utils/decorators/memoize';
import {ESLBaseElement, attr} from '../../esl-base-element/core';
import {TraversingQuery} from '../../esl-traversing-query/core';
import {EventUtils} from '../../esl-utils/dom/events';
import {compileFootnotesGroupedList, compileFootnotesNongroupedList} from './esl-footnotes-data';

import type {ESLNote} from './esl-note';
import type {FootnotesItem} from './esl-footnotes-data';

@ExportNs('Footnotes')
export class ESLFootnotes extends ESLBaseElement {
Expand All @@ -15,13 +17,22 @@ export class ESLFootnotes extends ESLBaseElement {
/** Target element {@link TraversingQuery} to define scope */
@attr({defaultValue: '::parent'}) public scopeTarget: string;

/** Grouping note instances with identical content enable/disable */
@attr({defaultValue: 'enable'}) public grouping: string;

protected _notes: ESLNote[] = [];

@memoize()
protected get scopeEl() {
return TraversingQuery.first(this.scopeTarget, this) as HTMLElement;
}

protected get footnotesList(): FootnotesItem[] {
return this.grouping !== 'enable'
? compileFootnotesNongroupedList(this._notes)
: compileFootnotesGroupedList(this._notes);
}

protected connectedCallback() {
super.connectedCallback();

Expand Down Expand Up @@ -65,24 +76,24 @@ export class ESLFootnotes extends ESLBaseElement {
}

protected buildItems(): string {
const items = this._notes.map((note) => this.buildItem(note)).join('');
const items = this.footnotesList.map((footnote) => this.buildItem(footnote)).join('');
return `<ul class="esl-footnotes-items">${items}</ul>`;
}

protected buildItem(note: ESLNote): string {
const item = `${this.buildItemIndex(note.index)}${this.buildItemText(note.html)}${this.buildItemBack()}`;
return `<li class="esl-footnotes-item" data-order="${note.index}">${item}</li>`;
protected buildItem(footnote: FootnotesItem): string {
const item = `${this.buildItemIndex(footnote)}${this.buildItemText(footnote)}${this.buildItemBack(footnote)}`;
return `<li class="esl-footnotes-item" data-order="${footnote.index}">${item}</li>`;
}

protected buildItemIndex(index: number): string {
return `<span class="esl-footnotes-index">${index}</span>`;
protected buildItemIndex(footnote: FootnotesItem): string {
return `<span class="esl-footnotes-index">${footnote.index}</span>`;
}

protected buildItemText(text: string): string {
return `<span class="esl-footnotes-text">${text}</span>`;
protected buildItemText(footnote: FootnotesItem): string {
return `<span class="esl-footnotes-text">${footnote.text}</span>`;
}

protected buildItemBack(): string {
protected buildItemBack(footnote: FootnotesItem): string {
return '<span class="esl-footnotes-back-to-note" tabindex="0"></span>';
}

Expand All @@ -99,12 +110,28 @@ export class ESLFootnotes extends ESLBaseElement {
protected _onClick(e: MouseEvent | KeyboardEvent) {
const target = e.target as HTMLElement;
if (target && target.classList.contains('esl-footnotes-back-to-note')) {
const index = target.parentElement?.getAttribute('data-order');
const note = index ? this._notes.find((el) => el.index === +index) : null;
note?.activate();
const orderAttr = target.parentElement?.getAttribute('data-order');
const order = orderAttr?.split(',').map((item) => +item);
order && this._onBackToNote(order);
}
}

protected _onBackToNote(order: number[]) {
const index = order[order.length - 1];
this._notes.forEach((note) => {
note.highlight(order.includes(note.index));
if (note.index === index) {
note.activate();
}
});
}

public turnOffHighlight(note: ESLNote) {
this._notes
.filter((item) => note.html === item.html)
.forEach((item) => item.highlight(false));
}

protected _sendRequestToNote() {
EventUtils.dispatch(this, `${ESLFootnotes.eventNs}:request`);
}
Expand Down
4 changes: 4 additions & 0 deletions src/modules/esl-footnotes/core/esl-note.less
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ esl-note {
&[tooltip-shown] {
text-decoration: underline;
}

&.highlight {
font-weight: bold;
}
}
16 changes: 16 additions & 0 deletions src/modules/esl-footnotes/core/esl-note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export class ESLNote extends ESLBaseElement {
return ESLMediaQuery.for(this.trackClick).matches;
}

static get observedAttributes() {
return ['tooltip-shown'];
}

get index(): number {
return this._index;
}
Expand All @@ -63,6 +67,13 @@ export class ESLNote extends ESLBaseElement {
this._$footnotes?.unlinkNote(this);
}

protected attributeChangedCallback(attrName: string, oldVal: string, newVal: string) {
if (!this.connected || oldVal === newVal) return;
if (attrName === 'tooltip-shown' && newVal === null) {
this._$footnotes?.turnOffHighlight(this);
}
}

protected bindEvents() {
document.body.addEventListener(`${ESLFootnotes.eventNs}:request`, this._onFootnotesReady);
this.addEventListener('click', this._onClick);
Expand All @@ -82,6 +93,10 @@ export class ESLNote extends ESLBaseElement {
scrollIntoViewAsync(this, {behavior: 'smooth', block: 'nearest'}).then(() => this.showTooltip());
}

public highlight(enable: boolean = true) {
this.classList.toggle('highlight', enable);
}

public link(footnotes: ESLFootnotes, index: number) {
this.linked = true;
this._$footnotes = footnotes;
Expand Down Expand Up @@ -112,6 +127,7 @@ export class ESLNote extends ESLBaseElement {
const actionParams = this.mergeToggleableParams({
}, params);
ESLTooltip.show(actionParams);
this.highlight();
}
/** Hide tooltip with passed params */
public hideTooltip(params: ToggleableActionParams = {}) {
Expand Down

0 comments on commit b14d28f

Please sign in to comment.