SW Core
SW Core / JavaScript / AJAX declarativo

AJAX declarativo JavaScript

Traz um pedaço de HTML do seu servidor e coloca na página quando a pessoa clica (ou passa o mouse, ou a página abre) — sem recarregar e sem escrever fetch().

O que é

Serve para "Ver mais detalhes", "Carregar comentários", abrir uma ficha num modal, trocar o conteúdo de uma área do painel. Você põe sw-ajax="/endereco" no botão e sw-target="#area" dizendo onde o HTML que voltar deve entrar. Pode também abrir o resultado direto num modal ou painel lateral criado na hora, pedir confirmação antes, animar a entrada e empilhar no histórico do navegador (o botão Voltar funciona).

Precisa do JavaScript do SW Core e de um endereço no seu servidor que devolva HTML (texto HTML, não JSON). O script busca o endereço, mostra um "carregando" no destino, limpa o HTML recebido (tira scripts e atributos perigosos) e coloca no lugar. Os componentes SW Core que vierem dentro (abas, modal, estrelas, outro sw-ajax…) já chegam funcionando. Por segurança, só busca no mesmo domínio do site, a não ser que você libere. Também dá para usar um <template> da própria página como fonte (sw-ajax-src), sem ir ao servidor.

Quando usar

  • Carregar sob demanda algo pesado ou pouco visto (comentários, ficha técnica, histórico): sw-ajax + sw-target.
  • Abrir detalhes num modal ou painel sem montar o modal antes: sw-ajax-target="modal" / "panel".
  • Ação perigosa que muda algo no servidor (excluir, arquivar): sw-ajax-method="POST" + sw-ajax-confirm.
  • Se o seu servidor devolve JSON, use o Conteúdo via JSON, que monta o HTML a partir de um modelo.

Comece aqui

  1. 1

    Coloque o SW Core na página.

    <link rel="stylesheet" href="swcore/swcore.min.css">
    
    <!-- fim do body -->
    <script src="swcore/swcore.min.js"></script>
  2. 2

    No servidor, um endereço que devolve só o pedaço de HTML (ex.: /produto/12/detalhes):

    <div class="detalhes">
      <h3>Café especial 500g</h3>
      <p>Torra média, notas de chocolate e caramelo.</p>
    </div>
  3. 3

    Na página: o botão diz de onde buscar (sw-ajax) e onde colocar (sw-target). Este exemplo busca de verdade um arquivo deste site.

    <button sw-btn="pri" sw-ajax="/produto/12/detalhes" sw-target="#detalhes">Ver detalhes</button>
    <div id="detalhes"></div>

Todas as variações

Cada quadro abaixo é o componente de verdade, rodando. O código embaixo é exatamente o que está no quadro: copie e cole.

1. De onde vem o conteúdo

sw-ajax busca um endereço no servidor (aqui, um arquivo de exemplo deste site). sw-ajax-src pega o conteúdo de um elemento da própria página — normalmente um <template>, que fica invisível até ser usado. Os demais quadros desta página usam <template> para funcionar até sem internet.

sw-ajax="endereço" — busca no servidor
<button sw-btn="pri p" sw-ajax="../../assets/demo-ajax.html" sw-target="#ajx-demo-1">Buscar no servidor</button>
<div id="ajx-demo-1"></div>
sw-ajax-src="#modelo" — usa um <template> da página
<button sw-btn="pri p" sw-ajax-src="#ajx-tpl-2" sw-target="#ajx-demo-2">Usar o template</button>
<div id="ajx-demo-2"></div>
<template id="ajx-tpl-2"><div class="bg-sur bd r-m p-2"><strong>Horário de atendimento</strong><p class="t-mut">Segunda a sexta, das 8h às 18h.</p></div></template>

2. Quando ele busca

sw-ajax-trigger: no clique (padrão), quando o mouse passa por cima (uma vez só) ou assim que a página abre.

click — padrão
<button sw-btn="out p" sw-ajax-src="#ajx-tpl-3" sw-target="#ajx-demo-3">Clique</button>
<div id="ajx-demo-3"></div>
<template id="ajx-tpl-3"><div class="bg-sur bd r-m p-2"><strong>Veio no clique</strong><p class="t-mut">É o jeito mais comum.</p></div></template>
sw-ajax-trigger="hover" — ao passar o mouse
<button sw-btn="out p" sw-ajax-src="#ajx-tpl-4" sw-target="#ajx-demo-4" sw-ajax-trigger="hover">Passe o mouse</button>
<div id="ajx-demo-4"></div>
<template id="ajx-tpl-4"><div class="bg-sur bd r-m p-2"><strong>Veio ao passar o mouse</strong><p class="t-mut">Bom para prévia rápida.</p></div></template>
sw-ajax-trigger="load" — assim que a página abre
<div sw-ajax-src="#ajx-tpl-5" sw-target="#ajx-demo-5" sw-ajax-trigger="load"></div>
<div id="ajx-demo-5"></div>
<template id="ajx-tpl-5"><div class="bg-sur bd r-m p-2"><strong>Veio sozinho</strong><p class="t-mut">Carregado quando a página abriu.</p></div></template>

3. Onde o conteúdo aparece

sw-target aponta uma área que já existe na página. Ou use sw-ajax-target="modal" / "panel": ele cria um modal ou painel lateral na hora, coloca o conteúdo e abre (feche com Esc ou clicando fora).

sw-target="#area" — numa área da página
<button sw-btn="out p" sw-ajax-src="#ajx-tpl-6" sw-target="#ajx-demo-6">Colocar aqui embaixo</button>
<div id="ajx-demo-6"></div>
<template id="ajx-tpl-6"><div class="bg-sur bd r-m p-2"><strong>Entrou na área</strong><p class="t-mut">O conteúdo anterior da área é substituído.</p></div></template>
sw-ajax-target="modal" — num modal criado na hora
<button sw-btn="pri p" sw-ajax-src="#ajx-tpl-7" sw-ajax-target="modal">Abrir no modal</button>
<template id="ajx-tpl-7"><div class="bg-sur bd r-m p-2"><strong>Ficha do produto</strong><p class="t-mut">Este conteúdo abriu num modal que o componente criou sozinho.</p></div></template>
sw-ajax-target="panel" — num painel lateral
<button sw-btn="pri p" sw-ajax-src="#ajx-tpl-8" sw-ajax-target="panel">Abrir no painel</button>
<template id="ajx-tpl-8"><div class="bg-sur bd r-m p-2"><strong>Filtros</strong><p class="t-mut">Painel lateral criado na hora.</p></div></template>

4. Animação de entrada

sw-ajax-effect recebe um efeito de animação do SW Core (os mesmos de sw-ani, como fade-up, pop, fade-left). Ajuste com sw-ajax-duration (ms), sw-ajax-distance e sw-ajax-delay (ms).

sw-ajax-effect="fade-up"
<button sw-btn="out p" sw-ajax-src="#ajx-tpl-9" sw-target="#ajx-demo-9" sw-ajax-effect="fade-up">Entrar subindo</button>
<div id="ajx-demo-9"></div>
<template id="ajx-tpl-9"><div class="bg-sur bd r-m p-2"><strong>Subiu</strong><p class="t-mut">Entrou com fade-up.</p></div></template>
sw-ajax-effect="pop" sw-ajax-duration="600"
<button sw-btn="out p" sw-ajax-src="#ajx-tpl-10" sw-target="#ajx-demo-10" sw-ajax-effect="pop" sw-ajax-duration="600">Entrar crescendo</button>
<div id="ajx-demo-10"></div>
<template id="ajx-tpl-10"><div class="bg-sur bd r-m p-2"><strong>Cresceu</strong><p class="t-mut">Entrou com pop em 600 ms.</p></div></template>

5. Pedir confirmação antes

sw-ajax-confirm mostra a caixa "Tem certeza?" do SW.Alert; só busca se a pessoa confirmar. Use em ações que mudam algo no servidor.

sw-ajax-confirm="…"
<button sw-btn="err p" sw-ajax-src="#ajx-tpl-11" sw-target="#ajx-demo-11" sw-ajax-confirm="Arquivar este pedido?">Arquivar pedido</button>
<div id="ajx-demo-11"></div>
<template id="ajx-tpl-11"><div class="bg-sur bd r-m p-2"><strong>Pedido arquivado</strong><p class="t-mut">Só apareceu porque você confirmou.</p></div></template>

Tabela de opções

PalavraO que fazExemplo
Fonte (um dos dois)
sw-ajaxEndereço a buscar. Precisa responder HTML (ou texto).sw-ajax="/produto/12/detalhes"
sw-ajax-srcSeletor de um elemento da página (ex.: <template>) cujo conteúdo será usado. Sem rede.sw-ajax-src="#modelo"
Destino (um dos dois)
sw-targetSeletor da área onde o conteúdo entra (o que estava lá é substituído).sw-target="#detalhes"
sw-ajax-target="modal"Cria/usa um modal e abre com o conteúdo. Para reaproveitar um modal seu, junte sw-modal-open="#id".sw-ajax-target="modal"
sw-ajax-target="panel"Cria/usa um painel lateral e abre. Para reaproveitar o seu: sw-panel-open="#id".sw-ajax-target="panel"
Quando
sw-ajax-trigger="click"No clique. Padrão.
sw-ajax-trigger="hover"Quando o mouse entra (uma vez só).sw-ajax-trigger="hover"
sw-ajax-trigger="load"Assim que a página abre.sw-ajax-trigger="load"
Envio
sw-ajax-methodGET (padrão) ou POST. No POST, se houver <meta name="csrf-token"> na página, o token vai junto sozinho. Os dados enviados são os campos do <form> (o próprio, ou o form onde o botão está). Num <form> em GET, os campos vão no endereço (?nome=…).sw-ajax-method="POST"
sw-ajax-confirmPergunta "tem certeza?" antes de buscar.sw-ajax-confirm="Excluir o pedido?"
sw-ajax-timeoutDesiste depois de N ms. Padrão 15000 (entre 1000 e 60000).sw-ajax-timeout="5000"
Resposta
sw-ajax-extractPega só um pedaço do HTML que voltou (seletor). Ótimo quando o endereço devolve uma página inteira.sw-ajax-extract="#conteudo"
sw-ajax-trustedNão limpa o HTML recebido. Só para HTML 100% seu.sw-ajax-trusted
sw-ajax-crossoriginLibera buscar em outro domínio (o outro servidor também precisa permitir).sw-ajax-crossorigin
Visual e histórico
sw-ajax-loader="off"Não mostra o "carregando" no destino.sw-ajax-loader="off"
sw-ajax-effectAnimação de entrada (nomes do sw-ani).sw-ajax-effect="fade-up"
sw-ajax-duration / -distance / -delayAjustes da animação: tempo (ms), distância, atraso (ms).sw-ajax-duration="600"
sw-ajax-pushMuda o endereço da barra do navegador; o botão Voltar refaz a troca.sw-ajax-push

Receitas prontas — usos reais

Situações que aparecem em quase todo site. Copie a que servir.

Aba de comentários que só carrega quando alguém pede Referência
<button sw-btn="out" sw-ajax="/posts/42/comentarios" sw-target="#comentarios">
  Ver comentários (18)
</button>
<section id="comentarios"></section>

<!-- /posts/42/comentarios devolve só o HTML dos comentários -->
Painel admin: navegar entre telas sem recarregar Referência
<nav>
  <a href="/admin/clientes" sw-ajax="/admin/clientes" sw-target="#tela"
     sw-ajax-extract="#tela" sw-ajax-push>Clientes</a>
  <a href="/admin/pedidos"  sw-ajax="/admin/pedidos"  sw-target="#tela"
     sw-ajax-extract="#tela" sw-ajax-push>Pedidos</a>
</nav>
<main id="tela">…</main>

<!-- cada endereço é uma página completa; sw-ajax-extract pega só o #tela dela.
     sw-ajax-push atualiza a barra de endereço e faz o Voltar funcionar.
     Sem JavaScript, os links continuam funcionando normalmente (href). -->
Excluir com confirmação e trocar a lista (POST) Referência
<meta name="csrf-token" content="<?= $csrf ?>">   <!-- vai sozinho no POST -->

<button sw-btn="err p"
        sw-ajax="/pedidos/1042/excluir"
        sw-ajax-method="POST"
        sw-ajax-confirm="Excluir o pedido #1042? Não dá para desfazer."
        sw-target="#lista-pedidos">Excluir</button>

<div id="lista-pedidos">…</div>
<!-- o servidor exclui e devolve o HTML da lista atualizada -->
Enviar um formulário e mostrar a resposta Referência
<!-- sw-ajax no <form>: dispara no envio (Enter ou botão submit) e manda os campos -->
<form sw-ajax="/orcamento" sw-ajax-method="POST" sw-target="#resposta">
  <input sw-inp name="nome" placeholder="Seu nome" required>
  <button sw-btn="pri" type="submit">Pedir orçamento</button>
</form>
<div id="resposta"></div>

<!-- ou por JavaScript:
     SW.Ajax.post('/orcamento', new FormData(form), '#resposta')
     (dados pode ser FormData ou um objeto, que vai como JSON) -->
Saber quando chegou ou falhou Referência
const botao = document.querySelector('#ver-detalhes');

botao.addEventListener('sw:ajax:start', (e) => console.log('buscando', e.detail.url));
botao.addEventListener('sw:ajax:done',  () => console.log('chegou e já está na tela'));
botao.addEventListener('sw:ajax:error', (e) => console.log('falhou', e.detail.error));
// em caso de erro ele já mostra um aviso vermelho (SW.Alert) e contorna o destino de vermelho

Eventos

sw:ajax:start
Começou a buscar no servidor. Traz e.detail.url. (Não dispara com sw-ajax-src.)
sw:ajax:done
O conteúdo chegou e já está na tela.
sw:ajax:error
Falhou (sem resposta, erro do servidor, demorou demais, resposta que não é HTML, domínio bloqueado). Traz e.detail.error.

API (JavaScript)

SW.Ajax.load(endereço, destino, opções?)
Busca e coloca no destino, pelo JavaScript. opções: { trusted, crossorigin, push, extract }.
SW.Ajax.post(endereço, dados, destino, opções?)
Envia por POST (dados = FormData ou objeto, que vai como JSON) e coloca a resposta no destino.
SW.Ajax.execute(elemento)
Dispara um elemento que já tem sw-ajax, como se tivesse sido clicado.

Precisa de quê

  • swcore.min.css e swcore.min.js.
  • No servidor: um endereço que responda com sucesso (código 200) e Content-Type: text/html (ou text/plain), no mesmo domínio do site.
  • Para POST com proteção CSRF: <meta name="csrf-token" content="…"> na página; o token vai no cabeçalho X-CSRF-Token.
  • A página precisa ser aberta por um endereço http(s):// — abrindo o arquivo direto do computador (file://) a busca não funciona.

Cuidados — erros comuns

  • Servidor devolvendo JSON: dá erro "Tipo de conteúdo não suportado". Este componente quer HTML. Para JSON, use o Conteúdo via JSON.
  • Esquecer o destino (sw-target ou sw-ajax-target): o aviso de erro aparece e nada entra na tela.
  • Endereço de outro domínio sem sw-ajax-crossorigin: é bloqueado de propósito.
  • Esperar que um <script> que veio na resposta rode: ele é removido na limpeza (mesmo com sw-ajax-trusted, script inserido assim não executa). Coloque o JavaScript na página e use os eventos.
  • Usar sw-ajax-trusted com conteúdo que o usuário escreveu (comentário, nome): abre espaço para ataque. Deixe a limpeza ligada.
  • Num <form> com sw-ajax, o disparo é no envio (Enter ou botão type="submit"). Um botão type="button" não envia — ele só dispara se tiver o próprio sw-ajax.

O que ele não faz

  • Não monta HTML a partir de JSON.
  • Não guarda em cache: cada clique busca de novo.
  • Um botão faz uma busca por vez: cliques repetidos enquanto carrega são ignorados.
  • O modal/painel criado por sw-ajax-target não tem título nem botão de fechar próprios — mande-os no HTML da resposta se precisar.
  • Com sw-ajax-push, voltar até antes da primeira troca recarrega a página inteira (ele não guarda o conteúdo original).