O que está faltando é uma compreensão da marcação semântica e do DOM.
Realisticamente, você pode fazer praticamente o que quiser com a marcação HTML5, e a maioria dos navegadores irá analisá-la. Da última vez que verifiquei, o WebKit / Blink permite até pseudo-elementos dentro de <input>
elementos , o que é uma violação clara das especificações - o Gecko nem tanto. No entanto, fazer o que quiser com a sua marcação irá, sem dúvida, invalidá-la no que diz respeito à semântica.
Por que colocamos <input>
elementos dentro de <form>
elementos? Pela mesma razão, colocamos <li>
tags dentro dos elementos <ul>
e <ol>
- é onde eles pertencem. É semanticamente correto e ajuda a definir a marcação. Analisadores, leitores de tela e vários softwares podem entender melhor sua marcação quando ela está semanticamente correta - quando a marcação tem significado, não apenas estrutura.
O <form>
elemento também permite definir os atributos method
e action
, que informam ao navegador o que fazer quando o formulário é enviado. O AJAX não é uma ferramenta de cobertura 100% e, como um desenvolvedor da web, você deve praticar a degradação normal - os formulários devem poder ser enviados e os dados transferidos, mesmo quando o JS está desligado.
Por fim, os formulários são todos devidamente registrados no DOM. Podemos dar uma olhada nisso com JavaScript. Se você abrir seu console nesta página e digitar:
document.forms
Você obterá uma boa coleção de todos os formulários da página. A barra de pesquisa, as caixas de comentários, a caixa de resposta - todos os formulários adequados. Essa interface pode ser útil para acessar informações e interagir com esses elementos. Por exemplo, os formulários podem ser serializados com muita facilidade.
Aqui está algum material de leitura:
Observação: os <input>
elementos podem ser usados fora dos formulários, mas se sua intenção for enviar dados de alguma forma, você deve usar um formulário.
Esta é a parte da resposta em que eu viro a pergunta.
Como estou dificultando minha vida evitando as formas?
Em primeiro lugar - elementos de contêiner. Quem precisa deles, certo ?!
Certamente seus elementos pequenos <input>
e <button>
estão aninhados dentro de algum tipo de elemento contêiner? Eles não podem simplesmente estar flutuando no meio de tudo o mais. Então, se não for um <form>
, então o quê? A <div>
? A <span>
?
Esses elementos precisam residir em algum lugar e, a menos que sua marcação seja uma bagunça maluca, o elemento contêiner pode ser apenas um formulário.
Não? Oh.
Neste ponto, as vozes em minha cabeça estão muito curiosas para saber como você cria seus manipuladores de eventos para todas essas diferentes situações AJAX. Deve haver muitos, se você precisar reduzir sua marcação para economizar bytes. Em seguida, você deve criar funções personalizadas para cada evento AJAX que corresponda a cada 'conjunto' de elementos - que você deve ter como alvo individualmente ou com classes, certo? Não há como agrupar esses elementos genericamente, uma vez que estabelecemos que eles apenas vagam pela marcação, fazendo tudo até que sejam necessários.
Então você customiza alguns manipuladores.
$('#searchButton').on('click', function (e) {
e.preventDefault();
var search = $('#mySearch');
$.ajax({
url: 'http://example.com/text',
type: 'GET',
dataType: 'text',
data: 'query=' + search.val(),
success: function (data) {
console.log(data);
}
});
});
$('#login').on('click', function (e) {
e.preventDefault();
var user = $('#username'),
pass = $('#password'),
rem = $('#remember');
$.ajax({
url: 'http://example.com/login',
type: 'POST',
data: user.add(pass, rem).serialize(),
dataType: 'text',
success: function (data) {
console.log(data);
}
});
});
<!-- No containers, extra markup is silly. -->
<input type="text" id="mySearch" value="query" />
<button id="searchButton">Search</button>
<input type="text" id="username" name="username" value="user" />
<input type="password" id="password" name="password" value="pass" />
<input type="checkbox" id="remember" name="remember" checked /> stay logged in
<button id="login">Login</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Esta é a parte em que você diz algo como:
'Eu uso totalmente funções reutilizáveis embora. Pare de exagerar. '
É justo, mas você ainda precisa criar esses conjuntos de elementos únicos, ou conjuntos de classes de destino, certo? Você ainda precisa agrupar esses elementos de alguma forma.
Empreste-me seus olhos (ou ouvidos, se você estiver usando um leitor de tela e precisar de alguma ajuda - boa coisa que poderíamos adicionar um pouco de ARIA a toda essa marcação semântica , certo?), E observe o poder da forma genérica.
function genericAjaxForm (e) {
e.preventDefault();
var form = $(this);
return $.ajax({
url: form.attr('action'),
type: form.attr('method'),
dataType: form.data('type'),
data: form.serialize()
});
}
$('#login-form').on('submit', function (e) {
genericAjaxForm.call(this, e).done(function (data) {
console.log(data);
});
});
<form action="http://example.com/login" method="POST" data-type="text" id="login-form">
<input type="text" name="username" value="user" />
<input type="password" name="password" value="mypass" />
<label>
<input type="checkbox" name="remember" /> Remember me
</label>
<button type="submit">Login</button>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Podemos usar isso com qualquer forma comum, manter nossa degradação elegante e deixar a forma descrever completamente como deve funcionar. Podemos expandir essa funcionalidade básica, mantendo um estilo genérico - mais modular, menos dores de cabeça. O JavaScript apenas se preocupa com suas próprias coisas, como ocultar os elementos apropriados ou lidar com qualquer resposta que obtivermos.
E agora você diz:
'Mas eu envolvo minhas pseudo-formas em <div>
elementos que têm IDs específicos - posso então direcionar as entradas vagamente com com .find
, e .serialize
eles, e ...'
Oh, o que é isso? Você realmente envolve seus <input>
elementos em um contêiner?
Então, por que ainda não é um formulário?