Sugestão de busca

Neste tutorial, veremos como adicionar as sugestões ao campo de pesquisa. Como funciona? Quando um usuário está digitando um texto para pesquisar, são sugeridos até 6 produtos de acordo com as letras ou palavras escritas.

HTML

1. A primeira coisa que vamos fazer é criar a pasta header dentro da pasta snipplets e em seguida, adicionar os seguintes snipplets com seus respectivos conteúdos.

É importante manter as classes "js -..." para garantir seu funcionamento quando adicionamos JavaScript.

header-search.tpl

<form class="js-search-container js-search-form" action="{{ store.search_url }}" method="get">
    <div class="form-group m-0">
        <input class="js-search-input form-control search-input" autocomplete="off" type="search" name="q" placeholder="{{ 'Buscar' | translate }}"/>
        <button type="submit" class="btn search-input-submit" value="">
            {% include "snipplets/svg/search.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
        </button>
    </div>
</form>
<div class="js-search-suggest search-suggest">
    {# AJAX container for search suggestions #}
</div>

header-search-results.tpl

<ul class="search-suggest-list">
    {% set search_suggestions = products | take(6) %}
    {% for product in search_suggestions %}
        <li class="search-suggest-item container-fluid">
            <a href="{{ product.url }}" class="search-suggest-link row justify-content-md-center">
                <div class="search-suggest-image-container col-xs-auto">
                    {{ product.featured_image | product_image_url("tiny") | img_tag(product.featured_image.alt, {class: 'search-suggest-image'}) }}
                </div>
                <div class="search-suggest-text col">
                    <p class="search-suggest-name">
                        {{ product.name | highlight(query) }}
                    </p>
                    {% if product.display_price %}
                        <p>
                            {{ product.price | money }}


                            {% set product_can_show_installments = product.show_installments and product.display_price and product.get_max_installments.installment > 1 %}
                            {% if product_can_show_installments %}
                                {% set max_installments_without_interests = product.get_max_installments(false) %}
                                {% if store.country == 'AR' %}
                                    {% set max_installments_with_interests = product.get_max_installments %}
                                    {% if max_installments_with_interests %}
                                        <span>| {{ "Hasta <strong class='installment-amount'>{1}</strong> cuotas" | t(max_installments_with_interests.installment, max_installments_with_interests.installment_data.installment_value_cents | money) }}</span>
                                    {% endif %}
                                {% else %}
                                    {% if max_installments_without_interests and max_installments_without_interests.installment > 1 %}
                                        <span>| {{ "<strong class='installment-amount'>{1}</strong> cuotas sin interés de <strong class='installment-price'>{2}</strong>" | t(max_installments_without_interests.installment, max_installments_without_interests.installment_data.installment_value_cents | money) }}</span>
                                    {% else %}
                                        {% set max_installments_with_interests = product.get_max_installments %}
                                        {% if max_installments_with_interests %}
                                            <span>| {{ "<strong class='installment-amount'>{1}</strong> cuotas de <strong class='installment-price'>{2}</strong>" | t(max_installments_with_interests.installment, max_installments_with_interests.installment_data.installment_value_cents | money) }}</span>
                                        {% endif %}
                                    {% endif %}
                                {% endif %}
                            {% endif %}
                        </p>
                    {% endif %}
                </div>
                <div class="col-xs-auto">
                    {% include "snipplets/svg/chevron-right.tpl" with {svg_custom_class: "icon-inline search-suggest-icon"} %}
                </div>
            </a>
        </li>
    {% endfor %}
    <a href="#" class="js-search-suggest-all-link btn btn-primary d-block">{{ 'Ver todos los resultados' | translate }}</a>
</ul>

O número de produtos sugeridos é definido no início do código: {% set search_suggestions = products | take(6) %}. Se você quiser mostrar outro valor, você pode fazer isso alterando o número de "take (B)"

2. Além disso, precisamos adicionar uma pasta SVG dentro da pasta snipplets. Aqui vamos adicionar os SVGs que usamos para os ícones na calculadora.

search.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M508.5 468.9L387.1 347.5c-2.3-2.3-5.3-3.5-8.5-3.5h-13.2c31.5-36.5 50.6-84 50.6-136C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c52 0 99.5-19.1 136-50.6v13.2c0 3.2 1.3 6.2 3.5 8.5l121.4 121.4c4.7 4.7 12.3 4.7 17 0l22.6-22.6c4.7-4.7 4.7-12.3 0-17zM208 368c-88.4 0-160-71.6-160-160S119.6 48 208 48s160 71.6 160 160-71.6 160-160 160z"/></svg>

chevron-right.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 512"><path d="M24.707 38.101L4.908 57.899c-4.686 4.686-4.686 12.284 0 16.971L185.607 256 4.908 437.13c-4.686 4.686-4.686 12.284 0 16.971L24.707 473.9c4.686 4.686 12.284 4.686 16.971 0l209.414-209.414c4.686-4.686 4.686-12.284 0-16.971L41.678 38.101c-4.687-4.687-12.285-4.687-16.971 0z"/></svg>

3. Finalmente, precisamos chamar o snipplet onde queremos exibir o mecanismo de busca, geralmente é no header. No layout Base, colocamos dentro de um modal.

{% snipplet "header/header-search.tpl" %}

CSS

Requisito:

Ter adicionado helper classes em seu layout. Você pode seguir este pequeno tutorial para fazer isso (é só copiar e colar algumas classes, não leva mais que 1 minuto).

1. Adicione estilos dentro do arquivo static/style-critical.tpl 

Se em seu design você usar um stylesheet para o CSS crítico, precisaremos do código abaixo nele, mas se não for o caso, você poderá unificar o CSS dos passos 1 e 2 em um único arquivo.

{# /* // Forms */ #}

.form-group {
  position: relative;
  width: 100%;
}
.form-group .form-select-icon{
  position: absolute;
  bottom: 12px;
  right: 0;
  pointer-events: none;
}
.form-row {
  width: auto;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
  margin-right: -5px;
  margin-left: -5px;
  clear: both;
}

.form-row > .col,
.form-row > [class*=col-]{
  padding-right: 5px;
  padding-left: 5px;
}

.form-label {
  display: block;
  font-size: 10px;
  text-transform: uppercase;
}

2. Adicione os estilos dentro do arquivo static/style-async.tpl

Se você não usar um stylesheet assíncrono no layout, adicione-o a outro código CSS.

{# /* // Search */ #}

.search-input {
  padding-right: 30px;
}

.search-input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance:none
}

.search-input-submit {
  position: absolute;
  top: 5px;
  right: 0;
  font-size: 18px;
  background: none;
  border: 0;
}

.search-suggest-list {
  margin: 0 0 10px 0;
  padding: 0;
}

.search-suggest-item {
  padding: 10px 15px;
  list-style: none;
}

.search-suggest-text,
.search-suggest-name {
  margin-bottom: 5px;
  line-height: 18px;
}
.search-suggest-icon {
  margin: 0 10px;
  font-size: 14px;
}

3. Adicionamos o seguinte SASS de cores em style-colors.scss.tpl (ou no stylesheet do seu layout que possui as cores e fontes da loja). Lembre-se de que as variáveis de cores e fontes podem variar em relação ao seu layout:

{# This mixin adds browser prefixes to a CSS property #}

@mixin prefix($property, $value, $prefixes: ()) {
    @each $prefix in $prefixes {
        #{'-' + $prefix + '-' + $property}: $value;
    }
       #{$property}: $value;
}

{# /* // Search */ #}

.search-suggest-item {
  border-bottom: 1px solid rgba($main-foreground, .1);
}

{# /* // Buttons */ #}

.btn{
  text-decoration: none;
  text-align: center;
  border: 0;
  cursor: pointer;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  text-transform: uppercase;
  background: none;
  @include prefix(transition, all 0.4s ease, webkit ms moz o);
  &:hover,
  &:focus{
    outline: 0;
    opacity: 0.8;
  }
  &[disabled],
  &[disabled]:hover{
    opacity: 0.5;
    cursor: not-allowed;
    outline: 0;
  }
  &-default{
    padding: 10px 15px; 
    background-color: rgba($main-foreground, .2);
    color: $main-foreground;
    fill: $main-foreground;
    font-weight: bold;
  }
  &-primary{
    padding: 15px;
    background-color: $primary-color;
    color: $main-background;
    fill: $main-background;
    letter-spacing: 4px;
    font-size: 12px;
    &:hover{
      color: $main-background;
      fill: $main-background;
    }
  }
}

JS

⚠️ A partir do dia 30 de janeiro de 2023, a biblioteca jQuery será removida do código de nossas lojas, portanto, a função "$" não poderá ser utilizada.

1. Precisamos adicionar o JavaScript no arquivo store.js.tpl (ou onde você tem suas funções JS). O código que precisamos é o seguinte:

{# /* // Search suggestions */ #}

LS.search(jQueryNuvem(".js-search-input"), function (html, count) {
    $search_suggests = jQueryNuvem(this).closest(".js-search-container").next(".js-search-suggest");
    if (count > 0) {
        $search_suggests.html(html).show();
    } else {
        $search_suggests.hide();
    }
    if (jQueryNuvem(this).val().length == 0) {
        $search_suggests.hide();
    }
}, {
    snipplet: 'header/header-search-results.tpl'
});

if (window.innerWidth > 768) {

    {# Hide search suggestions if user click outside results #}

    jQueryNuvem("body").on("click", function () {
        jQueryNuvem(".js-search-suggest").hide();
    });

    {# Maintain search suggestions visibility if user click on links inside #}

    jQueryNuvem(document).on("click", ".js-search-suggest a", function () {
        jQueryNuvem(".js-search-suggest").show();
    });
}

jQueryNuvem(".js-search-suggest").on("click", ".js-search-suggest-all-link", function (e) {
    e.preventDefault();
    $this_closest_form = jQueryNuvem(this).closest(".js-search-suggest").prev(".js-search-form");
    $this_closest_form.submit();
});

Traduções

Nesta etapa, adicionamos os textos para as traduções no arquivo config/translations.txt

es "Buscar"
pt "Buscar"
en "Search"
es_mx "Buscar"

es "Ver todos los resultados"
pt "Ver todos os resultados"
en "See all results"
es_mx "Ver todos los resultados"

es "Hasta 12 cuotas"
pt "Até 12x sem juros"
en "Upto 12x without interests"
es_mx "Hasta 12 cuotas"

es "Hasta <strong class='js-installment-amount installment-amount'>{1}</strong> cuotas"
pt "Até <strong class='js-installment-amount installment-amount'>{1}</strong>x"
en "Up to <strong class='js-installment-amount installment-amount'>{1}</strong> installments"
es_mx "Hasta <strong class='js-installment-amount installment-amount'>{1}</strong> meses"

es "<strong class='js-installment-amount installment-amount'>{1}</strong> cuotas de <strong class='js-installment-price installment-price'>{2}</strong>"
pt "<strong class='js-installment-amount installment-amount'>{1}</strong>x de <strong class='js-installment-price installment-price'>{2}</strong>"
en "In up to <strong class='js-installment-amount installment-amount'>{1}</strong> installments of <strong class='js-installment-price installment-price'>{2}</strong>"
es_mx "<strong class='js-installment-amount installment-amount'>{1}</strong> meses de <strong class='js-installment-price installment-price'>{2}</strong>"

es "<strong class='js-installment-amount installment-amount'>{1}</strong> cuotas sin interés de <strong class='js-installment-price installment-price'>{2}</strong>"
pt "<strong class='js-installment-amount installment-amount'>{1}</strong>x de <strong class='js-installment-price installment-price'>{2}</strong> sem juros"
en "In up to <strong class='js-installment-amount installment-amount'>{1}</strong> installments of <strong class='js-installment-price installment-price'>{2}</strong> without interest"
es_mx "<strong class='js-installment-amount installment-amount'>{1}</strong> meses sin intereses de <strong class='js-installment-price installment-price'>{2}</strong>"

es "En hasta <strong class='js-installment-amount installment-amount'>{1}</strong> cuotas"
pt "Em até <strong class='js-installment-amount installment-amount'>{1}</strong>x"
en "In up to <strong class='js-installment-amount installment-amount'>{1}</strong> installments"
es_mx "En hasta <strong class='js-installment-amount installment-amount'>{1}</strong> meses"