diff --git a/05-dom-document-loading/1-notification/index.js b/05-dom-document-loading/1-notification/index.js
index 2a95c5e..79bd10a 100644
--- a/05-dom-document-loading/1-notification/index.js
+++ b/05-dom-document-loading/1-notification/index.js
@@ -1,5 +1,6 @@
export default class NotificationMessage {
static lastShownNotification;
+ timerId;
constructor(messageText = '', props = {}) {
const {
@@ -45,7 +46,7 @@ export default class NotificationMessage {
}
hide() {
- setTimeout(() => this.remove(), this.duration);
+ this.timerId = setTimeout(() => this.remove(), this.duration);
}
remove() {
@@ -54,5 +55,6 @@ export default class NotificationMessage {
destroy() {
this.remove();
+ clearTimeout(this.timerId);
}
}
diff --git a/05-dom-document-loading/2-sortable-table-v1/index.js b/05-dom-document-loading/2-sortable-table-v1/index.js
index d40b94b..93f2152 100644
--- a/05-dom-document-loading/2-sortable-table-v1/index.js
+++ b/05-dom-document-loading/2-sortable-table-v1/index.js
@@ -1,6 +1,172 @@
export default class SortableTable {
+ subElements = {};
+ orderValue;
+ fieldValue;
+
constructor(headerConfig = [], data = []) {
+ this.headerConfig = headerConfig;
+ this.data = data;
+ this.element = this.createElement(this.createTemplate());
+ this.selectSubElements();
+ }
+
+ createElement(template) {
+ const element = document.createElement("div");
+ element.innerHTML = template;
+ return element.firstElementChild;
+ }
+
+ selectSubElements() {
+ this.element.querySelectorAll('[data-element]').forEach(element => {
+ this.subElements[element.dataset.element] = element;
+ });
+ }
+
+ createTableHeaderArrowTemplate() {
+ return `
+
+ `;
+ }
+
+ createTableHeaderCellTemplate(columnData) {
+ const isSortable = columnData.sortable && this.orderValue && columnData.id === this.fieldValue;
+ const dataOrder = isSortable ? `data-order="${this.orderValue}"` : '';
+ return `
+
+ ${columnData.title}
+ ${isSortable ? this.createTableHeaderArrowTemplate() : ''}
+
+ `;
+ }
+
+ createTableHeaderTemplate() {
+ return this.headerConfig.map(headerColumn => (
+ this.createTableHeaderCellTemplate(headerColumn)
+ )).join('');
+ }
+
+ createTableBodyCellTemplate(product, columnConfig) {
+ const id = columnConfig.id;
+
+ if (columnConfig.template) {
+ return columnConfig.template(product);
+ }
+ return (
+ `
+ ${product[id]}
+ `
+ );
+ }
+
+ createTableBodyRowTemplate(product) {
+ return (
+ `
+
+ ${this.headerConfig.map(column => this.createTableBodyCellTemplate(product, column)).join('')}
+
+ `
+ );
+ }
+
+ createTableBodyTemplate(data) {
+ return data.map((product) => (
+ this.createTableBodyRowTemplate(product)
+ )).join('');
+ }
+
+ createTemplate() {
+ return (
+ `
+
+
+
+ ${this.createTableBodyTemplate(this.data)}
+
+
+
+
+
+
No products satisfies your filter criteria
+
+
+
+
+ `
+ );
+ }
+
+ sortByType(sortType) {
+ if (sortType === 'number') {
+ return this.sortNumbers(this.data, this.fieldValue, this.orderValue);
+ }
+ if (sortType === 'string') {
+ return this.sortStrings(this.data, this.fieldValue, this.orderValue);
+ }
+ }
+
+ sortNumbers(data) {
+ if (this.orderValue === 'asc') {
+ return [...data].sort((a, b) => a[this.fieldValue] - b[this.fieldValue]);
+ }
+ if (this.orderValue === 'desc') {
+ return [...data].sort((a, b) => b[this.fieldValue] - a[this.fieldValue]);
+ }
+ return [...data];
+ }
+
+ sortStrings(data) {
+ if (this.orderValue === 'asc') {
+ return [...data].sort(
+ (a, b) => {
+ return a[this.fieldValue].localeCompare(b[this.fieldValue], ['ru', 'en'], { caseFirst: "upper" });
+ });
+ }
+ if (this.orderValue === 'desc') {
+ return [...data].sort(
+ (a, b) => {
+ return b[this.fieldValue].localeCompare(a[this.fieldValue], ['ru', 'en'], { caseFirst: "upper" });
+ });
+ }
+ return [...data];
+ }
+
+ sort(fieldValue, orderValue) {
+ this.fieldValue = fieldValue;
+ this.orderValue = orderValue;
+
+ this.setDataOrderAttribute(orderValue);
+
+ const sortType = this.headerConfig.find(obj => obj.id === fieldValue).sortType;
+ const sortedData = this.sortByType(sortType);
+
+ this.updateTemplate(sortedData);
+ }
+
+ setDataOrderAttribute() {
+ const sortableElems = document.body.querySelectorAll('.sortable-table__cell');
+ for (let element of sortableElems) {
+ element.setAttribute('data-order', this.orderValue);
+ }
+ }
+
+ updateTemplate(sortedData) {
+ this.subElements.header.innerHTML = this.createTableHeaderTemplate();
+ this.subElements.body.innerHTML = this.createTableBodyTemplate(sortedData);
+ }
+
+ remove() {
+ this.element.remove();
+ }
+ destroy() {
+ this.remove();
}
}