Aula 75 – Loja Online – Auto Search

Aula 75 – Loja Online – Auto Search

Loja Online - Django

Loja Online – Django

Pacote Programador Fullstack

Pacote Programador Fullstack

Voltar para página principal do blog

Todas as aulas desse curso

Aula 74                       Aula 76

Redes Sociais:

facebook

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Melhore seu NETWORKING

https://digitalinnovation.one/

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no https://github.com/toticavalcanti.

Código final da aula:

https://github.com/toticavalcanti

Quer aprender python3 de graça e com certificado? Acesse então:

https://workover.com.br/python-codigo-fluente

Canais do Youtube

Toti

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

PIX para doações

PIX Nubank

PIX Nubank


Aula 75 – Loja Online – Auto Search

Vamos implementar o auto search, para quando o usuário digitar alguma coisa na barra de pesquisa, o app já faça a busca automaticamente, depois de um certo tempo de parar a digitação.

Para começar vamos abrir o e_commerce/templates/base.html.

e_commerce/templates/base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){

        // Auto Search
        const searchForm = $(".search-form")
        const searchInput = searchForm.find("[name='q']")
        const typingTimer = 0;
        const typingInterval = 1500 // 1.5 seconds
        searchInput.keyup(function(event){
            console.log(event)
        })
        //Cart + Add Product
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
        event.preventDefault();
        // console.log("O formulário não foi enviado!");
        // o this pega os dados relacionados a esse form
        const thisForm = $(this);
        //const actionEndpoint = thisForm.attr("action");
        const actionEndpoint = thisForm.attr("data-endpoint");
        const httpMethod = thisForm.attr("method");
        const formData = thisForm.serialize();
        $.ajax({
          url: actionEndpoint,
          method: httpMethod,
          data: formData,
          success: function(data){
            // console.log("Sucesso")
            // console.log(data)
            // console.log("Adicionado", data.added)
            // console.log("Removido", data.removed)
            const submitSpan = thisForm.find(".submit-span")
            if(data.added){
              submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
            } else {
              submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
            }
            const navbarCount = $(".navbar-cart-count")
            navbarCount.text(data.cartItemCount)
            const currentPath = window.location.href
            if(currentPath.indexOf("cart") != -1){
              refreshCart()
            }
          },
          error: function(errorData){
            console.log("Erro")
            console.log(errorData)
          }
        })
      })
      function refreshCart(){
        //console.log("Excluído do carrinho atual!")
        const cartTable = $(".cart-table")
        const cartBody = cartTable.find(".cart-body")
        //cartBody.html("<h1>Mudou!</h1>")
        const productsRow = cartBody.find(".cart-product")
        const currentUrl = window.location.href 
        const refreshCartUrl = '/api/cart/';
        const refreshCartMethod = "GET";
        const data = {};
        $.ajax({
          url: refreshCartUrl,
          method: refreshCartMethod,
          data: data,
          success: function(data){
            console.log(data)
            const hiddenCartItemRemoveForm = $(".cart-item-remove-form")
            if(data.products.length > 0){
              productsRow.html(" ")
              let i = data.products.length
              $.each(data.products, function(index, value){
                const newCartItemRemove = hiddenCartItemRemoveForm.clone()
                newCartItemRemove.css("display", "block")
                newCartItemRemove.find(".cart-item-product-id").val(value.id)
                cartBody.prepend("<tr><th scope=\"row\">" + i + 
                "</th><td><a href='" + value.url + "'>" + 
                value.name + "</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
                i--
              })
              cartBody.find(".cart-subtotal").text(data.subtotal)
              cartBody.find(".cart-total").text(data.total)
            } else {
              window.location.href = currentUrl
              }
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        }
      })
    </script>
  </body>
</html>

Vamos colocar a classe search-form no form.

Com essa classe, poderemos fazer o update da pesquisa do usuário, a medida que ele vai digitando.

e_commerce/search/templates/search/snippets/search-form.html 


<form method='GET' action='{% url "search:query" %}' class="form my-2 my-lg-0 search-form">
  <div class="input-group">
    <input class="form-control" type="search" placeholder="Search" name='q' aria-label="Search" value='{{ request.GET.q }}'>
    <span class="input-group-btn">
      <button class="btn btn-outline-success" type="submit">Search</button>
    </span>
  </div>
</form>

O que vimos no console.log() foi só o evento.
Vamos acessar o valor digitado pelo usuário, dentro desse evento.

e_commerce/templates/base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){

        // Auto Search
        const searchForm = $(".search-form")
        const searchInput = searchForm.find("[name='q']")
        const typingTimer = 0;
        const typingInterval = 1500 // 1.5 seconds
        searchInput.keyup(function(event){
            console.log(searchInput.val())
            
        })

        //Cart + Add Product
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
        event.preventDefault();
        // console.log("O formulário não foi enviado!");
        // o this pega os dados relacionados a esse form
        const thisForm = $(this);
        //const actionEndpoint = thisForm.attr("action");
        const actionEndpoint = thisForm.attr("data-endpoint");
        const httpMethod = thisForm.attr("method");
        const formData = thisForm.serialize();
        $.ajax({
          url: actionEndpoint,
          method: httpMethod,
          data: formData,
          success: function(data){
            // console.log("Sucesso")
            // console.log(data)
            // console.log("Adicionado", data.added)
            // console.log("Removido", data.removed)
            const submitSpan = thisForm.find(".submit-span")
            if(data.added){
              submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
            } else {
              submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
            }
            const navbarCount = $(".navbar-cart-count")
            navbarCount.text(data.cartItemCount)
            const currentPath = window.location.href
            if(currentPath.indexOf("cart") != -1){
              refreshCart()
            }
          },
          error: function(errorData){
            console.log("Erro")
            console.log(errorData)
          }
        })
      })
      function refreshCart(){
        //console.log("Excluído do carrinho atual!")
        const cartTable = $(".cart-table")
        const cartBody = cartTable.find(".cart-body")
        //cartBody.html("<h1>Mudou!</h1>")
        const productsRow = cartBody.find(".cart-product")
        const currentUrl = window.location.href 
        const refreshCartUrl = '/api/cart/';
        const refreshCartMethod = "GET";
        const data = {};
        $.ajax({
          url: refreshCartUrl,
          method: refreshCartMethod,
          data: data,
          success: function(data){
            console.log(data)
            const hiddenCartItemRemoveForm = $(".cart-item-remove-form")
            if(data.products.length > 0){
              productsRow.html(" ")
              let i = data.products.length
              $.each(data.products, function(index, value){
                const newCartItemRemove = hiddenCartItemRemoveForm.clone()
                newCartItemRemove.css("display", "block")
                newCartItemRemove.find(".cart-item-product-id").val(value.id)
                cartBody.prepend("<tr><th scope=\"row\">" + i + 
                "</th><td><a href='" + value.url + "'>" + 
                value.name + "</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
                i--
              })
              cartBody.find(".cart-subtotal").text(data.subtotal)
              cartBody.find(".cart-total").text(data.total)
            } else {
              window.location.href = currentUrl
              }
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        }
      })
    </script>
  </body>
</html>

Agora vamos pegar o valor digitado e usar no auto search.

e_commerce/templates/base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){

        // Auto Search
        const searchForm = $(".search-form")
        const searchInput = searchForm.find("[name='q']")
        const typingTimer = 0;
        const typingInterval = 1500 // 1.5 seconds
        searchInput.keyup(function(event){
            clearTimeout(typingTimer)
            const typingTimer = setTimeout(peformSearch, typingInterval)
            
        })

        //Cart + Add Product
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
        event.preventDefault();
        // console.log("O formulário não foi enviado!");
        // o this pega os dados relacionados a esse form
        const thisForm = $(this);
        //const actionEndpoint = thisForm.attr("action");
        const actionEndpoint = thisForm.attr("data-endpoint");
        const httpMethod = thisForm.attr("method");
        const formData = thisForm.serialize();
        $.ajax({
          url: actionEndpoint,
          method: httpMethod,
          data: formData,
          success: function(data){
            // console.log("Sucesso")
            // console.log(data)
            // console.log("Adicionado", data.added)
            // console.log("Removido", data.removed)
            const submitSpan = thisForm.find(".submit-span")
            if(data.added){
              submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
            } else {
              submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
            }
            const navbarCount = $(".navbar-cart-count")
            navbarCount.text(data.cartItemCount)
            const currentPath = window.location.href
            if(currentPath.indexOf("cart") != -1){
              refreshCart()
            }
          },
          error: function(errorData){
            console.log("Erro")
            console.log(errorData)
          }
        })
      })
      function refreshCart(){
        //console.log("Excluído do carrinho atual!")
        const cartTable = $(".cart-table")
        const cartBody = cartTable.find(".cart-body")
        //cartBody.html("<h1>Mudou!</h1>")
        const productsRow = cartBody.find(".cart-product")
        const currentUrl = window.location.href 
        const refreshCartUrl = '/api/cart/';
        const refreshCartMethod = "GET";
        const data = {};
        $.ajax({
          url: refreshCartUrl,
          method: refreshCartMethod,
          data: data,
          success: function(data){
            console.log(data)
            const hiddenCartItemRemoveForm = $(".cart-item-remove-form")
            if(data.products.length > 0){
              productsRow.html(" ")
              let i = data.products.length
              $.each(data.products, function(index, value){
                const newCartItemRemove = hiddenCartItemRemoveForm.clone()
                newCartItemRemove.css("display", "block")
                newCartItemRemove.find(".cart-item-product-id").val(value.id)
                cartBody.prepend("<tr><th scope=\"row\">" + i + 
                "</th><td><a href='" + value.url + "'>" + 
                value.name + "</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
                i--
              })
              cartBody.find(".cart-subtotal").text(data.subtotal)
              cartBody.find(".cart-total").text(data.total)
            } else {
              window.location.href = currentUrl
              }
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        }
      })
    </script>
  </body>
</html>

Veja que estamos usando no django_ecommerce/e_commerce/templates/base/css.html o font-awesome.min.css.

Vamos usar ele para colocar uma animação de loading.

e_commerce/templates/base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){

        // Auto Search
        const searchForm = $(".search-form")
        const searchInput = searchForm.find("[name='q']")
        const typingTimer;
        const typingInterval = 1500 // 1.5 seconds
        const searchBtn = searchForm.find("[type='submit']")
        searchInput.keyup(function(event){
            clearTimeout(typingTimer)
            const typingTimer = setTimeout(peformSearch, typingInterval)
            
        })

        function displaySearching(){
            searchBtn.addClass("disabled")
            searchBtn.html("<i class='fa fa-spin fa-spinner'></i> Searching...")
        }

        function peformSearch(){
            displaySearching()
            const query = searchInput.val()
            window.location.href = '/search/?q=' + query
        }
        //Cart + Add Product
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
        event.preventDefault();
        // console.log("O formulário não foi enviado!");
        // o this pega os dados relacionados a esse form
        const thisForm = $(this);
        //const actionEndpoint = thisForm.attr("action");
        const actionEndpoint = thisForm.attr("data-endpoint");
        const httpMethod = thisForm.attr("method");
        const formData = thisForm.serialize();
        $.ajax({
          url: actionEndpoint,
          method: httpMethod,
          data: formData,
          success: function(data){
            // console.log("Sucesso")
            // console.log(data)
            // console.log("Adicionado", data.added)
            // console.log("Removido", data.removed)
            const submitSpan = thisForm.find(".submit-span")
            if(data.added){
              submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
            } else {
              submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
            }
            const navbarCount = $(".navbar-cart-count")
            navbarCount.text(data.cartItemCount)
            const currentPath = window.location.href
            if(currentPath.indexOf("cart") != -1){
              refreshCart()
            }
          },
          error: function(errorData){
            console.log("Erro")
            console.log(errorData)
          }
        })
      })
      function refreshCart(){
        //console.log("Excluído do carrinho atual!")
        const cartTable = $(".cart-table")
        const cartBody = cartTable.find(".cart-body")
        //cartBody.html("<h1>Mudou!</h1>")
        const productsRow = cartBody.find(".cart-product")
        const currentUrl = window.location.href 
        const refreshCartUrl = '/api/cart/';
        const refreshCartMethod = "GET";
        const data = {};
        $.ajax({
          url: refreshCartUrl,
          method: refreshCartMethod,
          data: data,
          success: function(data){
            console.log(data)
            const hiddenCartItemRemoveForm = $(".cart-item-remove-form")
            if(data.products.length > 0){
              productsRow.html(" ")
              let i = data.products.length
              $.each(data.products, function(index, value){
                const newCartItemRemove = hiddenCartItemRemoveForm.clone()
                newCartItemRemove.css("display", "block")
                newCartItemRemove.find(".cart-item-product-id").val(value.id)
                cartBody.prepend("<tr><th scope=\"row\">" + i + 
                "</th><td><a href='" + value.url + "'>" + 
                value.name + "</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
                i--
              })
              cartBody.find(".cart-subtotal").text(data.subtotal)
              cartBody.find(".cart-total").text(data.total)
            } else {
                  window.location.href = currentUrl
              }
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        }
      })
    </script>
  </body>
</html>

Pra gente ver melhor o efeito da animação do search, vou colocar o window.location.href = ‘/search/?q=’ + query dentro de um setTimeout().

E reduzir o intervalo de digitação, o typingInterval para meio segundo.

e_commerce/templates/base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){

        // Auto Search
        const searchForm = $(".search-form")
        const searchInput = searchForm.find("[name='q']") // input name='q'
        const typingTimer = 0;
        const typingInterval = 500 // .5 seconds
        const searchBtn = searchForm.find("[type='submit']")
        searchInput.keyup(function(event){
            // key released
            clearTimeout(typingTimer)
            typingTimer = setTimeout(performSearch, typingInterval)
        })
        searchInput.keydown(function(event){
            // key pressed
            clearTimeout(typingTimer)
        })
        function displaySearching(){
            searchBtn.addClass("disabled")
            searchBtn.html("<i class='fa fa-spin fa-spinner'></i> Searching...")
        }

        function performSearch(){
            displaySearching()
            var query = searchInput.val()
            setTimeout(function(){
              window.location.href='/search/?q=' + query
           }, 1000)
        }

        //Cart + Add Product
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
        event.preventDefault();
        // console.log("O formulário não foi enviado!");
        // o this pega os dados relacionados a esse form
        const thisForm = $(this);
        //const actionEndpoint = thisForm.attr("action");
        const actionEndpoint = thisForm.attr("data-endpoint");
        const httpMethod = thisForm.attr("method");
        const formData = thisForm.serialize();
        $.ajax({
          url: actionEndpoint,
          method: httpMethod,
          data: formData,
          success: function(data){
            // console.log("Sucesso")
            // console.log(data)
            // console.log("Adicionado", data.added)
            // console.log("Removido", data.removed)
            const submitSpan = thisForm.find(".submit-span")
            if(data.added){
              submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
            } else {
              submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
            }
            const navbarCount = $(".navbar-cart-count")
            navbarCount.text(data.cartItemCount)
            const currentPath = window.location.href
            if(currentPath.indexOf("cart") != -1){
              refreshCart()
            }
          },
          error: function(errorData){
            console.log("Erro")
            console.log(errorData)
          }
        })
      })
      function refreshCart(){
        //console.log("Excluído do carrinho atual!")
        const cartTable = $(".cart-table")
        const cartBody = cartTable.find(".cart-body")
        //cartBody.html("<h1>Mudou!</h1>")
        const productsRow = cartBody.find(".cart-product")
        const currentUrl = window.location.href 
        const refreshCartUrl = '/api/cart/';
        const refreshCartMethod = "GET";
        const data = {};
        $.ajax({
          url: refreshCartUrl,
          method: refreshCartMethod,
          data: data,
          success: function(data){
            console.log(data)
            const hiddenCartItemRemoveForm = $(".cart-item-remove-form")
            if(data.products.length > 0){
              productsRow.html(" ")
              let i = data.products.length
              $.each(data.products, function(index, value){
                const newCartItemRemove = hiddenCartItemRemoveForm.clone()
                newCartItemRemove.css("display", "block")
                newCartItemRemove.find(".cart-item-product-id").val(value.id)
                cartBody.prepend("<tr><th scope=\"row\">" + i + 
                "</th><td><a href='" + value.url + "'>" + 
                value.name + "</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
                i--
              })
              cartBody.find(".cart-subtotal").text(data.subtotal)
              cartBody.find(".cart-total").text(data.total)
            } else {
                  window.location.href = currentUrl
              }
            },
            error: function(errorData){
              console.log("Erro")
              console.log(errorData)
            }
          })
        }
      })
    </script>
  </body>
</html>

Essa mesma coisa pode ser usada para o auto save, da mesma forma que fizemos o auto search, alterando só os parâmetros.

Ficamos por aqui e até a próxima. 😉

Voltar para página principal do blog

Todas as aulas desse curso

Aula 74                       Aula 76

Código final da aula:

https://github.com/toticavalcanti

Canais do Youtube

Toti

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

Dêem um joinha 👍 na página do Código Fluente no
Facebook.

Sigam o Código Fluente no Instagram e no TikTok.

Código Fluente no Pinterest.

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Nos vemos na próxima então, \o/  😉 Bons Estudos!

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>