# Закрепите уведомление о новых или обновленных темах

**URL:** https://meta.discourse.org/t/sticky-see-new-or-updated-topic-notification/207371
**Category:** Support
**Created:** [28.Октябрь.2021 10:37:40 UTC](https://meta.discourse.org/t/sticky-see-new-or-updated-topic-notification/207371 "2021-10-28T10:37:40Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Don](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/don/32/228726_2.png) [@Don](https://meta.discourse.org/u/Don)
#### Post date: [28.Октябрь.2021 10:37:40 UTC](https://meta.discourse.org/t/sticky-see-new-or-updated-topic-notification/207371/1 "2021-10-28T10:37:40Z")

</div>

Здравствуйте,

Это может быть полезно, если бы строка **Показать x новых или обновлённых тем** оставалась зафиксированной в верхней части под заголовком, чтобы вы сразу видели её при прокрутке списка тем. При клике на эту строку страница будет прокручиваться к началу для загрузки новых или обновлённых тем.

Фиксация работает отлично с этим ⬇

```plaintext
#list-area .show-more.has-topics {
  position: sticky;
  top: var(--header-offset);
}

```

Вторая часть (JS) должна быть функцией для перехода в начало страницы или прокрутки к началу, но я не знаю, как это сделать или какой способ будет лучшим.

Я нашёл этот участок в шаблонах `discovery/topics.hbs` и `discovery/categories.hbs`. Если изменить `<a href` на `<a href="/"`, это может сработать _(не уверен, я не пробовал)_, но в этом случае при каждом клике будет происходить полная перезагрузка страницы, как при клике на логотип.

> <https://github.com/discourse/discourse/blob/8115e5ef76495e00297348eaf580fa0ce2741cc6/app/assets/javascripts/discourse/app/templates/discovery/topics.hbs#L33>

Спасибо за помощь 🙂

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [28.Октябрь.2021 15:04:03 UTC](https://meta.discourse.org/t/sticky-see-new-or-updated-topic-notification/207371/2 "2021-10-28T15:04:03Z")

</div>

> [@Don](#):
>
> Если изменить `href` в теге `<a` на `href="/"`, это может сработать _(не уверен, я не пробовал)_, но в этом случае при каждой загрузке будет происходить то же самое, что и при клике на логотип.

Да, добавление URL вызовет навигацию, так как нет логики для перехвата события.

Ссылка вызывает действие Ember. Все действия в Discourse расширяемы. Таким образом, они работают как хуки кастомизации. Так как же изменить действие? Давайте сначала посмотрим, что оно делает.

Ищите на GitHub или локально по имени действия. Действия всегда определяются в JS-файлах и упоминаются в Handlebars. Нам нужно увидеть определение, поэтому сузим поиск до JS-файлов.

[Repository search results · GitHub](https://github.com/discourse/discourse/search?l=JavaScript&q=showInserted)

Вы получите четыре файла. Какой из них нужно просмотреть? Вы хотите кастомизировать шаблон

`discovery/topics.hbs`.

Значит, вам нужен файл

`discovery/topics.js`.

[discourse/app/assets/javascripts/discourse/app/controllers/discovery/topics.js at e15bd194fde2c5ec21b216e7b594c543e8dc2739 · discourse/discourse · GitHub](https://github.com/discourse/discourse/blob/e15bd194fde2c5ec21b216e7b594c543e8dc2739/app/assets/javascripts/discourse/app/controllers/discovery/topics.js#L54-L62)

Помогает ли какой-то из этих фрагментов кода? Нет, но теперь мы знаем, где определено действие. Давайте его изменим.

`discovery/topics.js` — это класс Ember. Вы можете модифицировать классы Ember с помощью метода в plugin-api, который называется… modifyClass 😛

[https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/lib/plugin-api.js#L166-L195](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/lib/plugin-api.js#L166-L195)

Мы уже знаем класс, который хотим изменить. Это `discovery/topics`. Нам нужно понять, к какому типу классов он относится. Проверим структуру каталогов.

```plaintext
discourse/app/controllers/discovery/topics.js

```

Это контроллер.

Также мы знаем, что хотим изменить действие `showInserted` в этом классе. Начнём с этого:

```javascript
api.modifyClass("controller:discovery/topics", {
  pluginId: 'sticky-new-topics-banner',
  actions: {
    showInserted() {
      // давайте сделаем какую-то работу
    }
  }
});

```

Затем вы можете добавить любой код, который прокручивает окно при клике пользователя на баннер «новые темы». Я использовал что-то вроде этого:

```javascript
const listControls = document.querySelector(".list-controls");
listControls.scrollIntoView();

```

Подробнее о [scrollIntoView()](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) можно прочитать здесь.

Затем добавьте это в метод plugin-api следующим образом:

```diff
api.modifyClass("controller:discovery/topics", {
  pluginId: 'sticky-new-topics-banner',
  actions: {
    showInserted() {
+ const listControls = document.querySelector(".list-controls");
+ listControls.scrollIntoView();
    }
  }
});

```

Итак, мы закончили? Нет. Это ломает Discourse, потому что вы полностью переопределяете действие. При клике на ссылку теперь будет происходить прокрутка к элементу `list-controls`, но новые темы не загрузятся. Почему? Потому что код из ядра больше не выполняется. Имеется в виду вот этот код:

> <https://github.com/discourse/discourse/blob/e15bd194fde2c5ec21b216e7b594c543e8dc2739/app/assets/javascripts/discourse/app/controllers/discovery/topics.js#L54-L62>

Так как это исправить? С помощью одной простой строки:

```javascript
this._super(...arguments);

```

Вам не нужно копировать код из ядра, если вы просто хотите добавить что-то к нему. Выполните свою задачу, затем добавьте эту строку. Всё, что она делает, — гарантирует, что код из ядра будет применён.

```diff
api.modifyClass("controller:discovery/topics", {
  pluginId: 'sticky-new-topics-banner',
  actions: {
    showInserted() {
     const listControls = document.querySelector(".list-controls");
     listControls.scrollIntoView();
+
+ this._super(...arguments);
    }
  }
});

```

Если вы протестируете это, то увидите, что почти всё работает отлично, кроме одного… заголовок перекрывает `list-controls`. Почему? Потому что заголовок установлен как sticky.

Это можно исправить несколькими способами на JS — рассчитать высоту, получить смещение, импортировать вспомогательный метод из Discourse и т.д. Я не буду углубляться в эти варианты.

Самый простой способ — использовать CSS со свойством `scroll-margin-top`, о котором можно прочитать [здесь](https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top).

Добавим следующее:

```css
.list-controls {
  scroll-margin-top: calc(var(--header-offset) * 2);
}

```

По-русски: при клике на ссылку прокрутка должна остановиться на верхней части `list-controls` минус удвоенная высота заголовка, чтобы не было перекрытия и оставался небольшой отступ снизу.

Итак, давайте соберём всё вместе.

Вкладка common header:

```xml
<script type="text/discourse-plugin" version="0.8">
api.modifyClass("controller:discovery/topics", {
  pluginId: "sticky-new-topics-banner",
  actions: {
    showInserted() {
      const listControls = document.querySelector(".list-controls");
      listControls.scrollIntoView();
      this._super(...arguments);
    }
  }
});
</script>

```

Общие стили CSS:

```scss
#list-area {
  // на мобильных устройствах используется другая раскладка
  .alert-info,
  .show-more.has-topics {
    position: sticky;
    // Safari иногда капризен без префикса
    position: -webkit-sticky;
    top: var(--header-offset);
    // баннер должен быть поверх контента
    z-index: z("header");
  }
}

.list-controls {
  scroll-margin-top: calc(var(--header-offset) * 2);
}

```

---

<div class="post-metadata">

### Author: ![Don](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/don/32/228726_2.png) [@Don](https://meta.discourse.org/u/Don)
#### Post date: [28.Октябрь.2021 15:29:10 UTC](https://meta.discourse.org/t/sticky-see-new-or-updated-topic-notification/207371/3 "2021-10-28T15:29:10Z")

</div>

Спасибо, @Johani! Это очень помогло мне, и я, кажется, наконец-то понял многое. Мне очень нравятся ваши подробные ответы, потому что из них можно многому научиться: как всё устроено и, конечно же, как это работает. Ещё раз спасибо! 🙂

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [27.Ноябрь.2021 15:29:30 UTC](https://meta.discourse.org/t/sticky-see-new-or-updated-topic-notification/207371/4 "2021-11-27T15:29:30Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
