BOM em Javascript - Browser Object Model

BOM em Javascript (ou da forma longa – Browser Object Model) trata dos objetos que são relacionados com o navegador em si, tais como o já conhecido window, e elementos que estão abaixo dele, como location, document, navigator, e demais.

Não há um padrão oficial que possa ser discutido ou referenciado, algumas funções são suportadas por todos os navegadores, outras não. Neste artigo, vou tentar cobrir as funções que funcionam em todos os navegadores, além disso, vou passar alguns métodos para contornar problemas de compatibilidade que possam ocorrer em alguns desses navegadores.

BOM em Javascript

O Browser Object Model é formado por uma hierarquia de objetos, cada um em seu nível, acessíveis por um objeto pai de nível superior. O objeto mais acima de todos os outros é o que você já vem utilizando em alguns exemplos em nossos artigos anteriores, o objeto window.

No segundo nível, temos os objetos document, navigator, frames, location, history e screen. A partir de document, temos vários outros objetos e níveis, que são, provavelmente, os que você mais vai utilizar em seus trabalhos com Javascript.

Se você pesquisar no Google Imagens, rapidamente vai encontrar várias imagens especificando a estrutura do BOM em Javascript. Veja um exemplo abaixo:

Hierarquia do BOMImagem: daaq.net

A imagem acima representa bem o que eu estava dizendo anteriormente.

Você acessa cada um desses níveis utilizando um ponto (.) entre o objeto pai e o(s) objeto(s) filho(s), mas, em vários casos isso é gerado automaticamente pelo motor Javascript do navegador.

Veja no exemplo abaixo:

// Isso
window.alert(1);

// É o mesmo que isso
alert(1);

Uma propriedade de um dos objetos pode, ou não, ter suas próprias propriedades e métodos, ou pode referenciar vários outros objetos filhos com suas próprias propriedades e métodos.

Por exemplo, você pode acessar imagens dentro de document (que são todas as imagens da página) através do seu índice no array de imagens:

var img = document.images[0];

O índice é estruturado como já discutimos no artigo sobre validação de formulários em Javascript (0, 1, 2, 3, 4…). A ordem das imagens no índice do array é cadastrada de acordo com que as imagens são encontradas na página: a primeira (0), segunda (1), terceira (2).

O documento HTML é lido do topo para baixo, da direita para a esquerda, da mesma maneira que nós lemos livros, assim fica mais fácil para você entender como os índices das imagens (e de qualquer outro elemento em arrays) são cadastrados.

Outros elementos, como links, âncoras e formulários, também são acessíveis da mesma maneira que as imagens.

A propósito, se você quiser acessar todas as URLs (src) de todas as imagens de uma página, pode combinar a função que passei para você no artigo anterior para capturar o evento load da página, uma função genérica qualquer, e um laço for, como o exemplo abaixo:

// Função para capturar eventos
function captura_eventos(elemento, evento, funcao) {
    // Verifica se o navegador suporta addEventListener
    if(elemento.addEventListener) {
        elemento.addEventListener(evento, funcao, true);
    } else {
        // Adiciona attachEvent
        elemento.attachEvent('on' + evento, funcao);
    }
}

// Função geral que será carregada após o carregamento da página
function geral(){
    //Captura todas as imagens
    var imagens = document.images;
    
    // Percorre o array de imagens
    for(var i = 0; i < imagens.length; i++){
        // Imprime um alerta com o src (url) de todas as imagens
        alert(imagens[i].src);
    }
}

// Captura o evento load do objeto window e carrega a função geral
captura_eventos(window, 'load', geral);

Para entender, basta ler os comentários do código acima.

O objeto window

O objeto window engloba todo o BOM e Javascript, incluindo os eventos, alertas, outras janelas que possam ser abertas através da janela principal (famosos pop-ups), o endereço da página, o nome da página, e assim por diante. Por ser um objeto global, ele sempre está presente, mesmo que você não declare isso explicitamente no seu código.

Vamos ver alguns exemplos de janelinhas pop-up irritantes ao usuário.

Alert, confirm e prompt

Você como um usuário da Internet, provavelmente já deve conhecer os famosos alertas que aparecem na página quando faz algo incorreto, ou para confirmar alguma coisa.

Essas janelas não são necessariamente pop-ups, porém, trabalham de maneira parecida para informar algo ao usuário.

Um exemplo que estamos utilizando em praticamente todos os artigos sobre Javascript, é o alert, e não é por menos, essa é simplesmente a função mais fácil e rápida para apresentar uma caixa de diálogo para o usuário. A única coisa que ela precisa é de uma string contendo o que você deseja que apareça na tela.

alert("Boooooooooh!");

Além disso, não retorna valor nenhum, simplesmente a caixa de alerta e pronto.

Um outro tipo de caixa de diálogo que ainda é chato mas que é um pouco mais robusto do que o alert, é o confirm.

Esse tipo de diálogo é praticamente igual ao alert, porém, tem um botão de "OK" e outro de "Cancelar". Se o usuário clicar em "OK", retorna true, se o usuário clicar em "Cancelar", retorna false.

O bom dos valores booleanos retornados por confirm, é que você pode utilizar estruturas condicionais para fazer ou não fazer alguma ação:

// Confirmação
var confirma = confirm('Vai sair hoje?');

// Verifica se está confirmado
if(confirma){
    alert('Te pego às 6.');
} 
// Aqui vem a mensagem para o botão cancelar
else {
    alert('Ok, te ligo amanhã!');
}

Outra janelinha de diálogo que não deixa de ser chata, é a prompt. Ela é a mesma coisa da janela de confirmação, porém, tem um campo onde o usuário pode digitar algo; se ele digitar e pressionar "OK", o valor que ele digitou é retornado; se ele clicar em "Cancelar", um valor null é retornado.

// Confirmação
var pergunta = prompt('Vai sair hoje?', 'Vou!');

// Verifica se o usuário postou algum valor
if(pergunta){
    alert(pergunta);
} 
// Aqui vem a mensagem para o botão cancelar
else {
    alert('Valor nulo retornado!');
}

Uma dica: Evite utilizar qualquer um dos tipos de diálogo (alert, confirm e, principalmente, prompt), além dessas janelas serem chatas, alguns navegadores podem bloquear a janela de prompt nas medidas de segurança. Existem outros métodos bem mais amigáveis para alertar ou interagir com o usuário. Como você já deve ter percebido, ninguém utiliza esses tipos de caixas de diálogo hoje em dia.

Janela de Pop-up

Aqui está outra coisa que eu não aconselharia a ninguém utilizar, janelas chatas de pop-up. Sim! Se você pensou naquelas janelas que abrem quando você acessa um site suspeito falando que você ganhou um prêmio e deve clicar em algo para acontecer outro algo, são as próprias.

Porém, nem só de "pornografia" vive o mundo dos pop-ups. Há pouco tempo acessei o site do Detran-MG e lá estavam alguns pop-ups informativos, outro local onde encontro pop-ups vez em quando, é em sites de bancos, claro que estes também são informativos.

Enfim, para criar uma janela de pop-up em Javascript, você deve utilizar o método open do objeto window:

var nova_janela = window.open();

Sem nenhum parâmetro, window.open() abre uma aba em branco nos navegadores mais novos.

Você pode (deve) passar o primeiro parâmetro como a URL do site que deseja que abra (ou arquivo dentro do seu site), o nome da janela, e as opções, como: largura, altura, se os menus vão aparecer, se a barra de endereços vai aparecer e assim por diante. Veja um exemplo:

var nova_janela = window.open('http://todoespacoonline.com/w', 'tutsup', 'width=400');

O exemplo acima abre uma janela com o nosso blog e largura de 400 pixels (não é necessário escrever px no final da largura).

Existem milhares de opções que podem ser passadas no terceiro parâmetro, das quais você pode encontrar em Window open() Method. Tais opções devem ser separadas por vírgula e devem estar entre aspas, por exemplo:

var opcoes = 'width=400, height=400, location=no, menubar=no, scrollbars=no';
var nova_janela = window.open('http://todoespacoonline.com/w', 'tutsup', opcoes);

No trecho acima, ao invés de enviar as opções diretamente, criei uma variável contendo as mesmas. Fiz isso apenas para que o código ficasse mais fácil para ser lido.

Além disso, a variável contendo a nova janela pode ser manipulada de várias maneiras diferentes, por exemplo, você pode colocar um link dentro dela mesma para fechá-la utilizando self ao invés de window, ou posso fazer isso diretamente da janela mãe.

Vou mostrar um exemplo abaixo onde um link (<a>) fecha a janela:

// Função para abrir uma nova janela
function abre_janela(){
    var opcoes = 'width=400, height=400, location=no, menubar=no, scrollbars=no';
    var nova_janela = window.open('http://todoespacoonline.com/w', 'tutsup', opcoes);
    
    // Um elemento com id "a" fecha a janela ao ser clicado
    document.getElementById('a').onclick=function(){
        nova_janela.close();
        return false;
    }
}

window.location

O objeto location é bastante utilizado para obter ou manipular o endereço da página em que estamos trabalhando, por exemplo:

// Configura o endereço da página em uma variável
var endereco = location;

// Alerta o endereço
alert(endereco);

Location retorna o endereço completo da página, porém, existem propriedades que podem ser utilizadas com este objeto para obter determinadas partes do endereço, veja abaixo:

Propriedade Descrição
hash Retorna um fragmento de URL (Após #)
host Retorna o host e a porta utilizada
hostname Retorna o nome de host de uma URL
href Retorna a URL inteira
origin Retorna o protocolo, nome de host e a porta
pathname Retorna o caminho de uma URL
port Retorna a porta de uma URL
protocol Retorna o protocolo de uma URL
search Retorna os valores após o ponto de interrogação

Por exemplo:

// Configura o endereço da página em uma variável
var endereco = location;

// Alerta o endereço
alert(endereco.href);

Você também pode alterar o endereço da página, com os métodos: assign(), reload() e replace().

// Configura o endereço da página em uma variável
var endereco = location;

// Altera o endereço
endereco.assign('http://www.google.com.br');

Ou:

// Configura o endereço da página em uma variável
var endereco = location;

// Altera o endereço
endereco.replace('http://www.google.com.br');

Ou:

// Configura o endereço da página em uma variável
var endereco = location;

// Atualiza a página
endereco.reload();

Alerta: Tome cuidado com reload(), pois, se você criar uma página que chama este método no evento load, ela vai ficar atualizando constantemente e infinitamente.

Temporizadores

Duas funções bastante úteis para trabalhar com temporizadores em Javascript são setTimeout e setInterval. A primeira faz uma contagem regressiva e dispara uma função, a segunda trabalha com intervalos de tempo. Ambas aceitam dois parâmetros (nos IEs antigos), e do terceiro parâmetro em diante, eles se tornam os parâmetros da função:

setInterval(função, valor em milissegundos, parâmetros, da, função);

Veja um exemplo:

// Inicia uma variável com valor zero
var conta = 0;

// Função a ser disparada
function contador(){
    // Soma mais 1 na variável conta
    conta++;
    
    // Troca o valor do elemento com id parágrafo
    document.getElementById('paragrafo').innerHTML=conta;
}

// Configura o intervalo de 1 em 1 segundo (1000 milissegundos)
setInterval(contador, 1000);

No exemplo acima, um elemento com id parágrafo conta de segundo em segundo (1000 milissegundos) de 1 em diante (1, 2, 3…).

Para cancelar o temporizador de setInterval, você pode adicioná-lo em um variável qualquer e utilizar clearInterval(nome_da_variavel).

Exemplo:

// Inicia uma variável com valor zero
var conta = 0;

// Função a ser disparada
function contador(){
    // Soma mais 1 na variável conta
    conta++;
    
    // Troca o valor do elemento com id parágrafo
    document.getElementById('paragrafo').innerHTML=conta;
}

// Captura o evento de clique em qualquer parte do documento
document.onclick=function(){
    // Para de contar
    clearInterval(intervalo);
}

// Configura o intervalo de 1 em 1 segundo (1000 milissegundos)
var intervalo = setInterval(contador, 1000);

setTimeout é semelhante, porém, só faz uma contagem regressiva de acordo com os milissegundos enviados:

setTimeout(function(){
    alert('Se passaram 5 segundos!');
},5000);

Você também pode utilizar a função clearTimeout(nome_da_variavel) para zerar o tempo, porém, como a função será disparada apenas uma vez, é meio improvável que você faça isso.

Objeto history

Assim que você entra em uma página, Javascript ativa o objeto history e registra todas as URLs que você acessou, assim como os botões de página anterior e posterior do navegador fazem.

Você, como desenvolvedor, pode acessar este objeto para criar links para ir e voltar quantas páginas desejar, mesmo sem saber quais são esses links.

No exemplo abaixo, vou deixar meu arquivo Javascript de lado e vou mexer diretamente no HTML.

<a href="#" onclick="history.go(-1); return false;">Voltar</a>
<a href="#" onclick="history.go(1); return false;">Ir</a>

Os links acima capturam o evento click do link e enviam a função go() do objeto history. Essa função pode ir ou voltar quantas páginas você quiser, para ir, envie um valor positivo, para voltar, envie um valor negativo com o número de páginas desejadas. O return false; cancela a atualização de página padrão do elemento a.

Você pode fazer isso de um jeito moderno, se preferir, como falamos em nosso artigo sobre captura e manipulação de eventos em Javascript.

Objeto screen

O objeto screen contém informações sobre a tela do navegador do usuário que está acessando seu site, veja as opções:

Propriedade Description
availHeight Retorna a altura disponível no navegador
availWidth Retorna a largura disponível no navegador
colorDepth Retorna a profundidade de cores da tela
height Retorna a altura total da tela
pixelDepth Retorna os bits por pixel da tela
width Retorna a largura total da tela

Por serem apenas propriedades do objeto screen, não há muito o que falar sobre o objeto screen. Veja um exemplo:

alert(screen.availHeight);

Objeto navigator

Aqui está um objeto interessante se você quiser saber mais sobre o navegador do usuário.

O objeto navigator contém exatamente informações sobre o navegador do usuário, tais como: nome, versão, se os cookies estão ativos, a plataforma que ele está rodando e assim por diante.

Também não há muito o que falar sobre este objeto, as opções estão lá e você pode acessá-las quando quiser.

Veja todos os métodos e propriedades em:

Veja um exemplo:

alert(navigator.appName);
// Netscape (Estou no Firefox)

Objeto document

O document é um dos objetos mais importantes para a manipulação de elementos da página, na verdade, todos elementos HTML de uma página estão dentro desse objeto, e vamos examinar bastante suas propriedades e métodos em artigos posteriores.

Por agora, veremos apenas os elementos listados na imagem no começo deste artigos, que são referentes ao BOM em Javascript.

Links e anchors

Para acessar todos os links de uma página, você pode fazê-lo através do array links presente dentro do objeto document.

var urls = document.links;

Para percorrer o array, basta utilizar um laço for, veja no exemplo abaixo.

// Caputura o evento load da página
window.onload = function() {
    // Obtém um array com todos os links
    var urls = document.links;

    // Percorre o array dos links
    for (var i = 0; i < urls.length; i++) {
        // Alerta a referência dos links
        alert(urls[i].href);
    }
}

Após o carregamento da página, obtemos todos os links, e percorremos esses links dentro laço para exibir suas referências href (as URLs dentro deles).

Além disso, você também pode alterar atributos desses links. Por exemplo, suponhamos que eu queira alterar o atributo de referência (href):

// Caputura o evento load da página
window.onload = function() {
    // Obtém um array com todos os links
    var urls = document.links;

    // Percorre o array dos links
    for (var i = 0; i < urls.length; i++) {
        // Altera a referência dos links
        urls[i].href='#';
        // Configura um nome para o link
        urls[i].name='Novo nome';
        // Configura um título para o link
        urls[i].title='Título';
        // Munda o texto do link
        urls[i].innerHTML=urls[i].href;
    }
}

De fato, você pode alterar qualquer coisa utilizando Javascript.

A diferença entre links e âncoras, é que as âncoras não têm o atributo href, mas sim e o atributo name para referenciar alguma área da página:

<a name="ancora">Âncora</a>

Mas é quase a mesma coisa dos links para percorrê-las, veja abaixo:

// Caputura o evento load da página
window.onload = function() {
    // Obtém um array com todas as âncoras
    var urls = document.anchors;

    // Percorre o array dos links
    for (var i = 0; i < urls.length; i++) {
        // Altera a referência da âncora (cria nesse caso)
        urls[i].href='#';
        // Configura um nome para o link
        urls[i].name='Novo nome';
        // Configura um título para o link
        urls[i].title='Título';
        // Munda o texto do link
        urls[i].innerHTML=urls[i].href;
    }
}

Objeto forms

Não vou entrar em detalhes sobre o objeto forms, falamos muito sobre isso em nosso artigo sobre validação de formulários em Javascript, acesse e confira.

Objeto images

Da mesma forma que o objeto links, imagens podem ser acessadas com o objeto images:

window.onload=function(){
    // Obtém um array com todas as imagens do documento
    var imagens = document.images;
    
    // Percorre o array de imagens
    for(var i = 0; i < imagens.length; i++){
        // Altera o atributo src de todas as imagens
        imagens[i].src="test.png";
    }
}

O diferencial das imagens, é que você pode criar um novo elemento diretamente pelo objeto Image().

window.onload=function(){
    // Obtém um array com todas as imagens do documento
    var imagens = document.images;
    
    // Laço de duas voltas (CUIDADO AQUI)
    for(var i = 0; i < 1; i++){
        // Gera uma nova imagem
        var nova_imagem = new Image();
        // Seta o atributo da imagem presente no documento na nova imagem
        nova_imagem.src=imagens[i].src;
        // Adiciona a imagem em um elemento de ID "nova"
        document.getElementById('nova').appendChild(nova_imagem);
    }
}

No exemplo acima, estou gerando um clone de uma imagem que já existe no documento.

Você deve tomar cuidado com este tipo de laço, pois, pode se tornar um loop infinito.

O problema é que normalmente verificamos o tamanho do array de imagens para finalizar o laço, porém, como estamos incluindo uma nova imagem a cada volta do laço, o número de imagens nunca vai terminar, e quando você rodar este script, vai travar seu navegador de tantas imagens que vão tentar ser carregadas ao mesmo tempo. Por isso configurei o laço para terminar em duas voltas (0 e 1).

Outros elementos da página

Falamos bastante hoje sobre o BOM em Javascript (Browser Object Model) hoje, mas ainda temos muito para conversar sobre Javascript.

Nas próximas aulas, espero mostrar mais sobre tudo o que essa linguagem poderosa pode fazer por você, aprimorar mais seus conhecimentos sobre o DOM (Document Object Model), Cookies, a criação de seus próprios objetos, efeitos de página e muito mais.

Não perca as próximas aulas.

Outras aulas

Caso tenha perdido a aula anterior, segue o link:

Próxima aula:

Caso queira visualizar todas as aulas dessa sessão em ordem cronológica invertida: