Source:

carville-shop

Демо:

Плагины:

Подключение:

//

Разметка:

//
<ul class="tags-oems tags-oems--lessmore" id="lessmore-2">
  <li>
    <a
      href="#"
      data-popover-text="Копировать"
      data-copy-text="123123"
      class="js-text-popover-btn"
      >443615301
    </a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">443615301</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">443615301</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <a href="#">443615301</a>
  </li>
  <li>
    <a href="#">8W0615121E</a>
  </li>
  <li>
    <button
      class="btn-more js-lessmore-btn"
      data-target="#lessmore-2"
    >
      <span>Еще 6</span>
      <span>Скрыть</span>
      <svg class="icon" aria-hidden="true">
        <use xlink:href="#arrow-down"></use>
      </svg>
    </button>
  </li>
</ul>

Стили:

//

.tags-oems {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;

  a {
    transition: background-color 0.2s;
    display: block;
    padding: 0.8rem 1.2rem;
    border-radius: 3rem;
    background: #f6f6f6;
    font-size: 1.2rem;
    font-weight: 400;
    line-height: 1.4rem; /* 116.667% */

    &:hover {
      background: #e8e8e8;
    }
  }

  &--lessmore {
    &:not(.opened) {
      li {
        &:nth-child(n + 9) {
          display: none;
        }
      }
    }

    li:last-child {
      display: block !important;
    }
  }
}



.btn-more {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.8rem 0;
  font-size: 1.2rem;
  font-weight: 400;
  line-height: 1.4rem; /* 116.667% */
  color: #ff6e00;

  span:nth-child(2) {
    display: none;
  }

  .icon {
    font-size: 1.6rem;
  }

  &.opened {
    span:nth-child(1) {
      display: none;
    }
    span:nth-child(2) {
      display: block;
    }

    .icon {
      transform: rotate(180deg);
    }
  }
}

Инициализация:

interface ILessMoreOptions {
  btnOpenedClass?: string;
  listOpenedClass?: string;
}

class LessMore {
  private btnEl: HTMLElement;
  private listEl: HTMLElement;
  private options: Required<ILessMoreOptions>;
  private initializedClass = "lessmore-initialized";

  constructor(btnEl: HTMLAnchorElement, options: ILessMoreOptions = {}) {
    if (!btnEl) {
      throw new Error("LessMore: btnEl is required");
    }

    this.btnEl = btnEl;

    this.options = {
      btnOpenedClass: "opened",
      listOpenedClass: "opened",
      ...options,
    };

    const listSelector = btnEl.hash || btnEl.dataset.target;
    if (!listSelector) {
      throw new Error("LessMore: btn has not list selector");
    }

    const listEl = document.querySelector<HTMLElement>(listSelector);
    if (!listEl) {
      throw new Error("LessMore: listEl not found");
    }

    this.listEl = listEl;

    // Проверяем, есть ли уже созданный экземпляр
    const existing = (btnEl as any)._lessmoreInstance as LessMore;
    if (existing) return existing;

    this.init();

    // Сохраняем экземпляр в DOM
    (this.btnEl as any)._lessmoreInstance = this;
  }

  /** Инициализация кнопки */
  private init(): void {
    this.btnEl.classList.add(this.initializedClass);

    this.btnEl.addEventListener("click", this.handleButtonClick);
  }

  /** Обработчик клика */
  private handleButtonClick = (event: MouseEvent): void => {
    event.preventDefault();
    this.toggle();
  };

  /** Переключить состояние */
  public toggle(): void {
    if (this.btnEl.classList.contains(this.options.btnOpenedClass)) {
      this.close();
    } else {
      this.open();
    }
  }

  /** Открыть список */
  public open(): void {
    this.btnEl.classList.add(this.options.btnOpenedClass);
    this.listEl.classList.add(this.options.listOpenedClass);
  }

  /** Закрыть список */
  public close(): void {
    this.btnEl.classList.remove(this.options.btnOpenedClass);
    this.listEl.classList.remove(this.options.listOpenedClass);
  }

  /** Получить экземпляр по DOM-элементу */
  public static getInstance(btnEl: HTMLElement): LessMore | undefined {
    return (btnEl as any)._lessmoreInstance as LessMore | undefined;
  }

  /** Удалить экземпляр и обработчик */
  public destroy(): void {
    this.btnEl.classList.remove(this.initializedClass);
    this.btnEl.removeEventListener("click", this.handleButtonClick);
    delete (this.btnEl as any)._lessmoreInstance;
  }
}

export default LessMore;


export function initLessMore() {
  document
    .querySelectorAll<HTMLAnchorElement>(".js-lessmore-btn")
    .forEach((el) => {
      new LessMore(el, {
        btnOpenedClass: "opened",
        listOpenedClass: "opened",
      });
    });
}

Рубрики: Без рубрики

0 комментариев

Добавить комментарий

Avatar placeholder

Ваш адрес email не будет опубликован. Обязательные поля помечены *