Aula 1 de 0
Em Progresso

9.3 Manipular tabelas HTML

As tabelas são uma importante forma de exibir dados nas páginas HTML. As tags básicas para criar uma tabela são:

  • table para definir a tabela,
  • tr para criar uma nova linha
  • td para criar uma nova coluna em uma linha.
  • tag th que define uma célula de cabeçalho na tabela.

 

Para definir uma nova tabela via programação JavaScript, é possível utilizar os mesmos comandos das seções anteriores e indicar que um texto deve ser filho de td, td filho de tr e tr filho de table. Contudo, para facilitar a manipulação das tabelas em um programa, existem os métodos insertRow(num) e insertCell(nun), que inserem, respectivamente, uma linha e uma coluna na tabela. Então, pode-se criar uma tabela na página ou uma referência a uma tabela existente, e manipular sua estrutura adicionando novas linhas e colunas. Ambos os métodos recebem como parâmetro (num) a posição da linha ou coluna a ser inserida na tabela. 0 (zero) iden­tifica a linha ou coluna inicial. Para inserir uma linha no final da tabela, deve-se passar como argumento o valor -1.

 

Também é possível remover uma linha da tabela a partir do método deleteRow(num). O parâmetro indica o número da linha a ser removida. Já a propriedade length, sempre relacionada ao tamanho de um objeto, pode igualmente ser utilizada para recuperar o número de linhas da tabela a partir da instrução table.rows.length.

 

Outro importante recurso para a manipulação de tabelas via programação JavaS­cript é ter acesso ao conteúdo de uma célula da tabela, o que pode ser feito com a criação de referências aos índices que apontam para uma linha e coluna da tabela. Utilizar table.rows[0].cells[0] recupera o conteúdo da primeira célula da tabela. Ou seja, colocar essa instrução dentro de um laço de repetição vai permitir a obtenção de todo o conteúdo da tabela.

 

Vamos construir um exemplo que explora esses métodos e propriedades na mani­pulação de tabelas via JavaScript. O terceiro programa deste capítulo deve cadastrar filmes na localStorage e exibir uma tabela contendo título, gênero e uma coluna que permita ao usuário selecionar o filme para exclusão. A Figura 9.7 exibe a página desse programa com alguns filmes cadastrados.

 

Crie um novo arquivo HTML e salve-o com o nome de ex9_3.html. O código a ser inserido nesse arquivo é descrito no Exemplo 93.

 

 

 

 

 

 

Exemplo 9.3 – Página HTML que vai exibir uma tabela de filmes (ex9_3.html)

«1DOCTYPE htnl>
chtpíl lang="pt-br">
<head>
«neta charset=”UTF-8">
«neta nane="viewport" content="width=device-width, initial-scale=1.0">
«neta http-equiv="X-UA-Conpatible" content="ie=edge">
«link rel="stylesheet" href="css/bootstrap.nin.css">
«link rel="stylesheet" href="css/esttlos.css">
<titLe>Exenpl.o 9.3</title>
</head>
<body>
<div class="container-fluid">
«div class="row">
«div class="col-sn-4">
<tng src="ing/ex9_3.jpg" alt="Fi.lnes" cl.ass="ingProg">
</div>
«div class="coi-sn-8">
<hl>Meus Filnes Favoritos«/hl>
<p>
«labei for="inTitulo">Título do Filme:«/label>
<input type="text" class="form-control" id="inTitulo">
</p>
<p>
<label for="inGenero">Gênero:«/label>
«input type="text" class="form-control" id="inGenero">
</p>
<p class-'aDireita">
«input type="button" class="btn btn-primary" value="Adicionar" id="btAdicionar">
</p>
<table class="table table-striped" id="tbFilmes">
<tr>
<th>Título do Filme</th>
<th>Gênero</th>
<th>
<label><input type="checkbox" id="ckTodos"> Todos </label>
</th>
</tr>
</table>
«p class="aDireita">
«input type="button" class="btn btn-danger"
value="Excluir Selecionados" id="btExcluir">
</P>
</div>
</div>
</div>
«script src="js/ex9_3.js">«/script>
</body>
</html>

 

Observe que a tabela é inicialmente criada no código HTML, e sua linha de cabeça­lho, inserida. As demais linhas com os filmes informados pelo usuário serão acres­centadas pelo programa JavaScript. Vamos a ele… crie um novo arquivo e salve-o na pasta js com o nome ex9_3.js. Como o programa é grande, vamos apresentar suas funções em partes. Começamos pela function adicionarFilme().

 

Programa JavaScript que insere linhas e colunas em uma tabela (js/ex9_3.js)

function adicionarFilme() {
// cria referência aos campos de entrada
var inTitulo = document.getElementById("inTitulo");
var inGenero = docunent.getElementById("inGenero");
var titulo = inTitulo.value;	// obtém conteúdo dos campos
var genero = inGenero.value;
// valida preenchimento
if (titulo == "" || genero == "") {
alert("Informe corretamente os dados");
inTitulo.focus();
return;
}
// cria referência ao elemento tbFilmes
var tbFilmes = document.getElementById("tbFilmes");
// chama function que irá inserir filme na tabela inserirLinha(tbFilmes, titulo, genero);
// chama function que irá gravar dados em localStorage gravarFilme(titulo, genero);
inTitulo.value =	// limpa campos de entrada
inGenero.value = "";
inTitulo.focus(); // posiciona o cursor em inTitulo
}
var btAdicionar = document.getElementById("btAdicionar");
btAdicionar.addEventListener("click", adicionarFilme);

 

 

Essa função cria referência aos campos de entrada, valida o seu preenchimento e delega as tarefas de inserir uma nova linha na tabela e um novo filme na localS­torage às funções inserirLinha() e gravarFilme(). A function inserirLinha() contém as principais novidades dessa seção. Acrescente esse código no arquivo ex9_3. js.

 

 

function inserirLinha(tabela, titulo, genero) {
var linha = tabela.insertRow(-l); // adiciona uma linha na tabela
var coll = linha.insertCell(0); // cria colunas na linha inserida
var col2 = linha.insertCell(l);
var col3 = linha.insertCell(2);
coll.textContent = titulo;	// joga um conteúdo em cada célula
col2.textContent = genero;
col3.innerHTML = "<input type='checkbox'>"; // innerHTML renderiza código
}

 

 

Observe que a function recebe os parâmetros tabela, titulo e genero, sendo tabela uma referência à tbFilnes que é a table existente no código HTML. Nela, acrescentamos uma linha com o método insertRow(), em que -1 indica que a linha será inserida no final da tabela. O próximo passo é inserir as colunas nessa linha. Para isso, recorremos ao método insertCell(). E, por último, é feita a atribuição do conteúdo de cada célula.

 

Para que o campo tipo checkbox seja renderizado na terceira coluna da tabela, utili­zamos a propriedade innerHTML discutida na seção 2.5. Essa é uma forma segura de utilizar essa propriedade, visto que o conteúdo a ser renderizado não vem de um campo preenchido pelo usuário, e sim de um dado fixo inserido pelo programa.

Caso você tenha ficado com alguma dúvida quanto à diferença entre as propriedades textContent e innerHTML, faça o seguinte teste: substitua a innerHTML por textContent e rode o programa. Você vai observar que com textContent o navegador exibe o texto <input type.. .>, e não uma caixa de seleção para o usuário selecionar.

Vamos então à segunda function chamada pelo adicionarFilme(). Ela recebe os parâ­metros titulo e genero e os grava em localStorage. Para separar os filmes, é utilizado o delimitador

 

 

function gravarFilme(titulo, genero) {
// se há filmes salvos em localStorare ...
if (localStorage.getItem("filmesTitulo")) {
// ... obtém os dados e acrescenta e o título/gênero informado
var filmesTitulo = localStorage.getItem("filmesTitulo") +	+ titulo;
var filmesGenero = localStorage.getItem("filmesGenero") +	+ genero;
localStorage.setltem( "filmesTitulo", filmesTitulo);	// grava dados
localStorage.setltem("filmesGenero", filmesGenero);	// em localStorage
} else {
// senão, é a primeira inclusão (salva sem delimitador) localStorage. setltem("filmesTitulo", titulo);
localStorage. setltem("filmesGenero", genero);
}
}

 

 

A partir das funções apresentadas, o programa lê os dados informados pelo usu­ário, exibe-os nas tabelas a partir dos métodos insertRow() e insertCell() e os salva em localStorage. A função destacada a seguir visa recuperar os dados dos filmes salvos em localStorage e os exibir quando a página for carregada. Assim, o usuário não perde a sua lista de filmes favoritos salvos na execução anterior do programa.

 

 

function recuperarFilmes() {
//se houver dados salvos em localStorage
if (localStorage.getItem("filmesTitulo")) {
// obtém conteúdo e converte em elementos de vetor (na ocorrência ";")
var titulos = localStorage.getItem("filmesTitulo").split(";");
var generos = localStorage.getltem("filmesGenero").split(";");
// cria referência ao elemento tbFilmes
var tbFilmes = document.getElementById("tbFilmes");
// percorre elementos do vetor e os insere na tabela
for (var i = 0; i < titulos.length; i++) {
inserirLinha(tbFilmes, titulosfi], generos[i]);
}
}
}
recuperarFilmesO;

 

 

A function recuperarFilmesO verifica se há dados salvos em localStorage e, se houver, joga o conteúdo de cada campo em elementos de vetor. Em seguida, cria refe­rência à tabela tbFilmes para que na repetição possa também chamar a function inserirLinha() que fará a exibição dos dados na página. Você pode testar o funcio­namento do programa com as funções criadas até este ponto. Elas são responsáveis pelo processo de inclusão e exibição dos dados em uma tabela da página.

As funções discutidas a seguir permitem remover os filmes da tabela e também da localStorage. Começamos pela discussão da function anônima associada ao evento change do checkbox ckTodos. Ao clicar sobre ele, todos os filmes são marcados ou desmarcados, conforme ilustra a Figura 9.8.

Acrescente as seguintes linhas ao programa ex9_3.js. Então, faça o teste e observe que, quando clicado, o status de ckTodos é atribuído a todos os filmes da tabela.

 

 

 

 

 

 

 

JJJ

// cria referência ao checkbox ckTodos (na linha de título da tabela)
var ckTodos = document.getElementById("ckTodos");
// executa função anônima quando houver una troca de status
ckTodos.addEventListener("change", function () {
// cria referência à tabela e aos canpos input (filhos da tabela)
var tbFilmes = docunent.getElenentById("tbFilnes");
var ckExcluir = tbFilmes.getElementsByTagName("input");
var status = ckTodos.checked; // obtém status de ckTodos ...
// ... e percorre os demais checkbox para aplicar este status
for (var i = 1; i < ckExcluir.length; i++) {
ckExcluir[i].checked = status;
}
});

 

 

Naturalmente, esse código poderia ficar em uma função nomeada como as demais desse programa. Vamos retomando alguns recursos discutidos ao longo do livro para relembrá-los. Sobre a function, observe que é criada uma referência à tag table tbFilmes e, em seguida, todos os campos input filhos de tbFilmes são recupe­rados com o método getElementsByTagName(). Na sequência do programa, obtém-se o status de ckTodos (marcado ou desmarcado) para aplicá-lo a todos os inputs da tabela, a partir de uma estrutura de repetição. Perceba que no for a variável i inicia com o valor 1, pois o input de índice 0 é o próprio ckTodos.

 

A function removerFilme() é um pouco mais complexa, pois envolve as ações de remover o filme da localStorage e também retirar uma linha da tabela. Acrescente essa última function no arquivo ex9_3. js para concluir o nosso programa de cadastro de filmes.

 

function removerFilmesO {
// cria referência à tabela e aos campos input (filhos da tabela)
var tbFilmes = document.getElementById("tbFilmes");
var ckExcluir = tbFilmes.getElementsByTagName("input");
var temSelecionado = false; // para verificar se há filmes selecionados
// percorre campos input type checkbox da tabela (exceto "Todos" no título)
for (var i = 1; i < ckExcluir.length; i++) {
if (ckExcluir[i].checked) {	// se está selecionado
temSelecionado = true;	// muda valor da "flag"
break;	// sai da repetição
}
}
//se não temSelecionado (se valor da variável é false)
if (!temSelecionado) {
alert("Não há filmes selecionados para exclusão");
return;
}
// solicita confirmação de exclusão dos filmes selecionados
if (confirm("Confirma Exclusão dos Filmes Selecionados?")) {
// exclui conteúdo armazenado em localStorage
localStorage. removeltem( "filmesTitulo");
localStorage. removeltem( "filmesGenero");
// primeiro irá gravar em localStorage os filmes não selecionados
for (i = 1; i < ckExcluir.length; i++) {
// se não está selecionado (para exclusão)
íf (!ckExcluír[í].checked) {
// obtém o conteúdo da tabela (coluna 0: título; coluna 1: gênero)
var titulo = tbFílnes.rows[í].cells[0].textContent;
var genero = tbFílnes.rows[í].cells[l].textContent;
gravarFílne(título, genero); // chama gravarFílne com dados da tabela
}
}
// agora irá remover as linhas selecionadas (do fim para o início)
for (i = ckExcluir.length - 1; i > 0; i--) {
if (ckExcluir[i].checked) {
tbFilmes.deleteRow(i); // remove a linha
}
}
ckExcluir[0].checked = false; // desmarca ckTodos (que é o input 0)
}
}
var btExcluir = document.getElementById("btExcluir");
btExcluir.addEventListener("clíck", removerFilmes);

 

 

 

As duas primeiras linhas de código da function remover Filmes () são idênticas às da função anônima discutida anteriormente, pois aqui também é necessário recuperar os campos input filhos de tbFilmes. Em seguida, temos um conjunto de comandos utilizados para verificar se há algum filme selecionado para exclusão, a fim de alertar o usuário e evitar a execução desnecessária de comandos.

O processo de exclusão ocorre se o usuário confirmar a execução dessa tarefa no if contendo o método confirm(). Para isso, primeiro se removem as variáveis arma­zenadas em localStorage (o usuário poderia ter selecionado todos os filmes para exclusão). Na sequência, obtém-se o conteúdo das células da tabela das linhas não marcadas e chama-se a function que grava esses dados em localStorage. Remover tudo primeiro para depois incluir novamente parece um pouco estranho… Mas, para essa estrutura de armazenamento, é o modo mais simples de executar essa tarefa.

O terceiro e último for dessa function visa retirar os filmes exibidos na tabela. Um detalhe importante nessa etapa é que a repetição deve ocorrer do final para o início, pois os índices dos elementos são alterados dinamicamente quando se remove um deles. Assim, se excluirmos primeiro o filme de índice 0, todos os demais sobem uma posição e a exclusão não funcionaria corretamente se mais de um filme esti­vesse selecionado.

Como destacado no capítulo anterior, os dados armazenados na Local Storage podem ser excluídos se o usuário limpar o histórico de navegação em seu browser. Portanto, cuidado com as informações salvas nesse local pelos programas desen­volvidos em nossos exemplos. Eles objetivam simular o processo de persistência de dados e devem ser substituídos por aplicações que enviam dados para Web Services a fim de evitar possíveis perdas de dados.

Estamos nos aproximando do final do livro. O próximo capítulo contém mais alguns exemplos com programas maiores como esse último de cadastro de filmes. Selecionei três exercícios de fixação dos assuntos abordados neste capítulo para você praticar o que foi visto aqui. Um ótimo trabalho!! Ah… não se esqueça de que um exemplo de resposta com o programa de cada enunciado está disponível no site da editora.