Создание иконки поиска с темой

Привет!

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

Однако это не сработало.

<script>
node = document.getElementsByClassName('search-page-heading');
node.insertAdjacentElements('beforebegin', '<svg class="PixlzThemeSearchIcon" aria-hidden="true"><use xlink:href="#search"></use></svg>');
</script>

Возможно, я допустил глупую ошибку (как некоторые из вас знают, ночью я становлюсь ещё глупее), но буду благодарен за помощь.
Спасибо!

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

Если я правильно понимаю, вы хотите добавить иконку поиска на страницу поиска :arrow_down_small:

Для этого, по-видимому, потребуется переопределить шаблон Discourse.
Вот как это сделать: Переопределение шаблонов Discourse, но я рекомендую прочитать всю документацию.


В данном случае это выглядит примерно так. Сначала нужно найти шаблон страницы поиска. Вот список шаблонов: https://github.com/discourse/discourse/tree/main/app/assets/javascripts/discourse/app/templates

Нам нужен шаблон full-page-search.hbs, и мы можем четко увидеть, какую часть нужно изменить для внесения этих правок.

Это заголовочная часть шаблона, которую мы будем редактировать… но это чуть позже…

    <h1 class="search-page-heading">
      {{#if this.hasResults}}
        <div class="result-count" id="search-result-count" aria-live="polite">
          {{html-safe this.resultCountLabel}}
        </div>
      {{else}}
        {{i18n "search.full_page_title"}}
      {{/if}}
    </h1>

Теперь, исходя из документации выше, мы должны начать так:

Шаблон помещается в секцию header.

<script type="text/x-handlebars" data-template-name="full-page-search">

</script>

Затем нужно скопировать внутрь весь шаблон:

Выглядит так
<script type="text/x-handlebars" data-template-name="full-page-search">
  <DSection @pageClass="search" @class="search-container">
    <ScrollTracker @name="full-page-search" @tag={{this.searchTerm}} @class="hidden" />
    <div class="search-header" role="search">
      <h1 class="search-page-heading">
        {{#if this.hasResults}}
          <div class="result-count" id="search-result-count" aria-live="polite">
            {{html-safe this.resultCountLabel}}
          </div>
        {{else}}
          {{i18n "search.full_page_title"}}
        {{/if}}
      </h1>
      <div class="search-bar">
        <SearchTextField @value={{this.searchTerm}} @class="full-page-search search no-blur search-query" @aria-label={{i18n "search.search_term_label"}} @enter={{action "search" (hash collapseFilters=true)}} @hasAutofocus={{this.hasAutofocus}} @aria-controls="search-result-count" />
        <ComboBox @id="search-type" @value={{this.search_type}} @content={{this.searchTypes}} @onChange={{action (mut this.search_type)}} @options={{hash
            castInteger=true
          }} />
        <DButton @action={{action "search" (hash collapseFilters=true)}} @icon="search" @label="search.search_button" @class="btn-primary search-cta" @ariaLabel="search.search_button" @disabled={{this.searchButtonDisabled}} />
      </div>
      {{#if this.usingDefaultSearchType}}
        {{!-- context is only provided when searching from mobile view --}}
        {{#if this.context}}
          <div class="search-context">
            <label>
              <Input @type="checkbox" name="searchContext" @checked={{this.searchContextEnabled}} /> {{this.searchContextDescription}}
            </label>
          </div>
        {{/if}}

        <div class="search-filters">
          <SearchAdvancedOptions @searchTerm={{readonly this.searchTerm}} @onChangeSearchTerm={{action (mut this.searchTerm)}} @search={{action "search" (hash collapseFilters=true)}} @searchButtonDisabled={{this.searchButtonDisabled}} @expandFilters={{this.expandFilters}} />
        </div>
      {{/if}}

      <div class="search-notice">
        {{#if this.invalidSearch}}
          <div class="fps-invalid">
            {{i18n "search.too_short"}}
          </div>
        {{/if}}
      </div>

    </div>

    <div class="search-advanced">
      {{#if this.hasResults}}
        {{#if this.usingDefaultSearchType}}
          <div class={{this.searchInfoClassNames}} role="region" ariaLabel={{i18n "search.sort_or_bulk_actions"}}>
            {{#if this.canBulkSelect}}
              <DButton @icon="list" @class="btn-default bulk-select" @title="topics.bulk.toggle" @action={{action "toggleBulkSelect"}} />
              {{#if this.selected}}
                <DButton @class="btn-default bulk-select-btn" @selected={{this.selected}} @action={{action "showBulkActions"}} @icon="wrench" />
              {{/if}}
            {{/if}}

            {{#if this.bulkSelectEnabled}}
              {{#if this.hasUnselectedResults}}
                <DButton @icon="check-square" @class="btn-default" @action={{action "selectAll"}} @label="search.select_all" />
              {{/if}}

              {{#if this.hasSelection}}
                <DButton @icon="far-square" @class="btn-default" @action={{action "clearAll"}} @label="search.clear_all" />
              {{/if}}
            {{/if}}

            <div class="sort-by inline-form">
              <label>
                {{i18n "search.sort_by"}}
              </label>
              <ComboBox @value={{this.sortOrder}} @content={{this.sortOrders}} @onChange={{action (mut this.sortOrder)}} @id="search-sort-by" @options={{hash
                  castInteger=true
                }} />
            </div>
          </div>
        {{/if}}
      {{/if}}

      <PluginOutlet @name="full-page-search-below-search-info" @tagName="span" @connectorTagName="div" @args={{hash search=this.searchTerm}} />

      {{#if this.searching}}
        {{loading-spinner size="medium"}}
      {{else}}
        <div class="search-results" role="region">
          <LoadMore @selector=".fps-result" @action={{action "loadMore"}}>
            {{#if this.usingDefaultSearchType}}
              <SearchResultEntries @posts={{this.model.posts}} @bulkSelectEnabled={{this.bulkSelectEnabled}} @selected={{this.selected}} @highlightQuery={{this.highlightQuery}} @searchLogId={{this.model.grouped_search_result.search_log_id}} />

              <ConditionalLoadingSpinner @condition={{this.loading}}>
                {{#unless this.hasResults}}
                  {{#if this.searchActive}}
                    <h3>{{i18n "search.no_results"}}</h3>

                    {{#if this.model.grouped_search_result.error}}
                      <div class="warning">
                        {{this.model.grouped_search_result.error}}
                      </div>
                    {{/if}}

                    {{#if this.showSuggestion}}
                      <div class="no-results-suggestion">
                        {{i18n "search.cant_find"}}
                        {{#if this.canCreateTopic}}
                          <a href {{action "createTopic" this.searchTerm}}>{{i18n "search.start_new_topic"}}</a>
                          {{#unless this.siteSettings.login_required}}
                            {{i18n "search.or_search_google"}}
                          {{/unless}}
                        {{else}}
                          {{i18n "search.search_google"}}
                        {{/if}}
                      </div>

                      <GoogleSearch @searchTerm={{this.searchTerm}} />
                    {{/if}}
                  {{/if}}
                {{/unless}}

                {{#if this.hasResults}}
                  <h3 class="search-footer">
                    {{#if this.model.grouped_search_result.more_full_page_results}}
                      {{#if this.isLastPage}}
                        {{i18n "search.more_results"}}
                      {{/if}}
                    {{else}}
                      {{i18n "search.no_more_results"}}
                    {{/if}}
                  </h3>
                {{/if}}
              </ConditionalLoadingSpinner>
            {{else}}
              <ConditionalLoadingSpinner @condition={{this.loading}}>
                {{#if this.hasResults}}
                  {{#if this.model.categories.length}}
                    <h4 class="category-heading">
                      {{i18n "search.categories"}}
                    </h4>
                    <div class="category-items">
                      {{#each this.model.categories as |category|}}
                        {{category-link category extraClasses="fps-category-item"}}
                      {{/each}}
                    </div>
                  {{/if}}

                  {{#if this.model.tags.length}}
                    <h4 class="tag-heading">
                      {{i18n "search.tags"}}
                    </h4>

                    <div class="tag-items">
                      {{#each this.model.tags as |tag|}}
                        <div class="fps-tag-item">
                          <a href={{tag.url}}>
                            {{tag.id}}
                          </a>
                        </div>
                      {{/each}}
                    </div>
                  {{/if}}

                  {{#if this.model.users}}
                    <div class="user-items">
                      {{#each this.model.users as |user|}}
                        <UserLink @user={{user}} @class="fps-user-item">
                          {{avatar user imageSize="large"}}

                          <div class="user-titles">
                            {{#if user.name}}
                              <span class="name">
                                {{user.name}}
                              </span>
                            {{/if}}

                            <span class="username">
                              {{user.username}}
                            </span>
                          </div>
                        </UserLink>
                      {{/each}}
                    </div>
                  {{/if}}
                {{else}}
                  {{#if this.searchActive}}
                    <h3>{{i18n "search.no_results"}}</h3>
                  {{/if}}
                {{/if}}
              </ConditionalLoadingSpinner>
            {{/if}}
          </LoadMore>
        </div>
      {{/if}}
    </div>
  </DSection>
</script>

Теперь мы можем отредактировать заголовочную часть, о которой я упоминал ранее. В данном случае это очень простое изменение, но вы можете внести и более сложные правки. Убедитесь, что ваш пользовательский шаблон всегда актуален. Если в основном шаблоне произойдут какие-либо изменения, вам также следует обновить свой пользовательский шаблон, чтобы всё работало корректно. :slightly_smiling_face:

В данном случае мы просто добавляем иконку {{d-icon "search"}} перед заголовком полной страницы и перед количеством результатов.

Полный шаблон выглядит так :arrow_down_small:

<script type="text/x-handlebars" data-template-name="full-page-search">
  <DSection @pageClass="search" @class="search-container">
    <ScrollTracker @name="full-page-search" @tag={{this.searchTerm}} @class="hidden" />
    <div class="search-header" role="search">
      <h1 class="search-page-heading">
        {{#if this.hasResults}}
          <div class="result-count" id="search-result-count" aria-live="polite">
            {{d-icon "search"}}
            {{html-safe this.resultCountLabel}}
          </div>
        {{else}}
          {{d-icon "search"}}
          {{i18n "search.full_page_title"}}
        {{/if}}
      </h1>
      <div class="search-bar">
        <SearchTextField @value={{this.searchTerm}} @class="full-page-search search no-blur search-query" @aria-label={{i18n "search.search_term_label"}} @enter={{action "search" (hash collapseFilters=true)}} @hasAutofocus={{this.hasAutofocus}} @aria-controls="search-result-count" />
        <ComboBox @id="search-type" @value={{this.search_type}} @content={{this.searchTypes}} @onChange={{action (mut this.search_type)}} @options={{hash
            castInteger=true
          }} />
        <DButton @action={{action "search" (hash collapseFilters=true)}} @icon="search" @label="search.search_button" @class="btn-primary search-cta" @ariaLabel="search.search_button" @disabled={{this.searchButtonDisabled}} />
      </div>
      {{#if this.usingDefaultSearchType}}
        {{!-- context is only provided when searching from mobile view --}}
        {{#if this.context}}
          <div class="search-context">
            <label>
              <Input @type="checkbox" name="searchContext" @checked={{this.searchContextEnabled}} /> {{this.searchContextDescription}}
            </label>
          </div>
        {{/if}}

        <div class="search-filters">
          <SearchAdvancedOptions @searchTerm={{readonly this.searchTerm}} @onChangeSearchTerm={{action (mut this.searchTerm)}} @search={{action "search" (hash collapseFilters=true)}} @searchButtonDisabled={{this.searchButtonDisabled}} @expandFilters={{this.expandFilters}} />
        </div>
      {{/if}}

      <div class="search-notice">
        {{#if this.invalidSearch}}
          <div class="fps-invalid">
            {{i18n "search.too_short"}}
          </div>
        {{/if}}
      </div>

    </div>

    <div class="search-advanced">
      {{#if this.hasResults}}
        {{#if this.usingDefaultSearchType}}
          <div class={{this.searchInfoClassNames}} role="region" ariaLabel={{i18n "search.sort_or_bulk_actions"}}>
            {{#if this.canBulkSelect}}
              <DButton @icon="list" @class="btn-default bulk-select" @title="topics.bulk.toggle" @action={{action "toggleBulkSelect"}} />
              {{#if this.selected}}
                <DButton @class="btn-default bulk-select-btn" @selected={{this.selected}} @action={{action "showBulkActions"}} @icon="wrench" />
              {{/if}}
            {{/if}}

            {{#if this.bulkSelectEnabled}}
              {{#if this.hasUnselectedResults}}
                <DButton @icon="check-square" @class="btn-default" @action={{action "selectAll"}} @label="search.select_all" />
              {{/if}}

              {{#if this.hasSelection}}
                <DButton @icon="far-square" @class="btn-default" @action={{action "clearAll"}} @label="search.clear_all" />
              {{/if}}
            {{/if}}

            <div class="sort-by inline-form">
              <label>
                {{i18n "search.sort_by"}}
              </label>
              <ComboBox @value={{this.sortOrder}} @content={{this.sortOrders}} @onChange={{action (mut this.sortOrder)}} @id="search-sort-by" @options={{hash
                  castInteger=true
                }} />
            </div>
          </div>
        {{/if}}
      {{/if}}

      <PluginOutlet @name="full-page-search-below-search-info" @tagName="span" @connectorTagName="div" @args={{hash search=this.searchTerm}} />

      {{#if this.searching}}
        {{loading-spinner size="medium"}}
      {{else}}
        <div class="search-results" role="region">
          <LoadMore @selector=".fps-result" @action={{action "loadMore"}}>
            {{#if this.usingDefaultSearchType}}
              <SearchResultEntries @posts={{this.model.posts}} @bulkSelectEnabled={{this.bulkSelectEnabled}} @selected={{this.selected}} @highlightQuery={{this.highlightQuery}} @searchLogId={{this.model.grouped_search_result.search_log_id}} />

              <ConditionalLoadingSpinner @condition={{this.loading}}>
                {{#unless this.hasResults}}
                  {{#if this.searchActive}}
                    <h3>{{i18n "search.no_results"}}</h3>

                    {{#if this.model.grouped_search_result.error}}
                      <div class="warning">
                        {{this.model.grouped_search_result.error}}
                      </div>
                    {{/if}}

                    {{#if this.showSuggestion}}
                      <div class="no-results-suggestion">
                        {{i18n "search.cant_find"}}
                        {{#if this.canCreateTopic}}
                          <a href {{action "createTopic" this.searchTerm}}>{{i18n "search.start_new_topic"}}</a>
                          {{#unless this.siteSettings.login_required}}
                            {{i18n "search.or_search_google"}}
                          {{/unless}}
                        {{else}}
                          {{i18n "search.search_google"}}
                        {{/if}}
                      </div>

                      <GoogleSearch @searchTerm={{this.searchTerm}} />
                    {{/if}}
                  {{/if}}
                {{/unless}}

                {{#if this.hasResults}}
                  <h3 class="search-footer">
                    {{#if this.model.grouped_search_result.more_full_page_results}}
                      {{#if this.isLastPage}}
                        {{i18n "search.more_results"}}
                      {{/if}}
                    {{else}}
                      {{i18n "search.no_more_results"}}
                    {{/if}}
                  </h3>
                {{/if}}
              </ConditionalLoadingSpinner>
            {{else}}
              <ConditionalLoadingSpinner @condition={{this.loading}}>
                {{#if this.hasResults}}
                  {{#if this.model.categories.length}}
                    <h4 class="category-heading">
                      {{i18n "search.categories"}}
                    </h4>
                    <div class="category-items">
                      {{#each this.model.categories as |category|}}
                        {{category-link category extraClasses="fps-category-item"}}
                      {{/each}}
                    </div>
                  {{/if}}

                  {{#if this.model.tags.length}}
                    <h4 class="tag-heading">
                      {{i18n "search.tags"}}
                    </h4>

                    <div class="tag-items">
                      {{#each this.model.tags as |tag|}}
                        <div class="fps-tag-item">
                          <a href={{tag.url}}>
                            {{tag.id}}
                          </a>
                        </div>
                      {{/each}}
                    </div>
                  {{/if}}

                  {{#if this.model.users}}
                    <div class="user-items">
                      {{#each this.model.users as |user|}}
                        <UserLink @user={{user}} @class="fps-user-item">
                          {{avatar user imageSize="large"}}

                          <div class="user-titles">
                            {{#if user.name}}
                              <span class="name">
                                {{user.name}}
                              </span>
                            {{/if}}

                            <span class="username">
                              {{user.username}}
                            </span>
                          </div>
                        </UserLink>
                      {{/each}}
                    </div>
                  {{/if}}
                {{else}}
                  {{#if this.searchActive}}
                    <h3>{{i18n "search.no_results"}}</h3>
                  {{/if}}
                {{/if}}
              </ConditionalLoadingSpinner>
            {{/if}}
          </LoadMore>
        </div>
      {{/if}}
    </div>
  </DSection>
</script>

Надеюсь, это поможет :slightly_smiling_face:

Ладно, почти получилось!

Я изменил поисковый баннер, и он делает вот это


Никогда не думал, что это будет так сложно, но спасибо! Думал, это будет простой скрипт на JS из трёх строк

Да, я думаю, это из-за вашего пользовательского CSS. Вам, вероятно, нужно настроить эту область. :slightly_smiling_face:

Извините за поздний ответ, но вот CSS для этого.

svg.PixlzThemeSearchIcon {
      position: relative;
      display: table-row;
      height: 50px !important;
      width: 50px;
      top: 227px;
      left: 220px;
      fill: #e0e0e0;
}

Есть ли в нём какие-либо ошибки?

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

Вам не нужно добавлять кастомный CSS для SVG, если вы хотите, чтобы он отображался перед заголовком, так как мы разместили его внутри тегов h2, поэтому он будет использовать стили h2. Однако вам нужно изменить секцию заголовка поиска. Если я не ошибаюсь, приведенный выше скриншот сделан из вашей темы DarkPixlz’s Modern Theme?

Я проверил эту тему и считаю, что проблема в том, что вы используете большие отступы (padding) и размер шрифта для центрирования заголовка, из-за чего для иконки поиска не остаётся достаточно места.

.search-container .search-page-heading {
  padding: 2em 3.8em;
  font-size: 5em;
}

Мое предложение:

Вместо отступов (padding) используйте внешние отступы (margins), но не по бокам — так как у .search-header уже есть отступы 10% по бокам — чтобы освободить место для иконки, а также уменьшите размер шрифта, особенно на мобильных устройствах. Чтобы исправить вертикальное выравнивание, добавьте верхний отступ (margin) в 1em, так как у .main-outlet есть верхний отступ (padding) в 3em.

Возможно, будет лучше, если я изменю фон.

.search-container .search-page-heading {
  margin: 1em 0 2em 0;
  font-size: 5em; // используйте меньший размер шрифта на экранах меньшего размера
  text-align: center;
}

Спасибо, сработало :slight_smile: