jQuery – Criando uma classe para Modal

Estava estudando algumas coisas de jQuery em um tempo livre no trampo e comecei a desenvolver uma classe de modal para jQuery. Sei que já existem várias, lightbox, facebox, e outras, mas fiz para estudar mesmo.

Nunca havia feito um modal do zero – sei que usei uma biblioteca, então não foi do zero mesmo mesmo – mas achei a experiência bem satisfatória e menos traumática do que eu pensava.

Vou explicar primeiro o que a classe se propõem a fazer

Requisitos

  • Biblioteca jQuery

 

Funcionalidades

  • Pode criar diversos modais (iniciando a classe mais de uma vez)
  • Carrega imagens (jpg,jpeg,gif,png) e ajusta o modal no tamanho da imagem
  • Carrega elementos de objetos html da página no modal
  • Carrega html externo (ajax) no modal
  • Gera as funções para todos os links utilizando o atributo "rel"

 

Bugs conhecidos

  • Não redimensiona a altura do modal para um tamanho menor do atual (no IE)

Devem existir mais, pelo que lembro até tinha relatado mais alguns, mas esqueci de anotar e aí… 😛

Testei o modal em Firefox, Internet Explorer 8, Internet Explorer 7 (emulado), Internet Explorer 6 (emulado). Tenho algumas idéias que gostaria de implementar mas nem testei ainda, segue a lista para quem quiser se arriscar:

  • Navegação entre os contents ou imagens do modal
  • Melhorar o sistema de resize
  • Melhorar o layout
  • Implementar exibição de vídeos do Youtube diretamente do link

 

O código

O código estava bem simples até eu começar a fazer alguns ajustes para o IE.. mas enfim, como é típico do jQuery, acredito que o código está bem "legível", segue a classe:

 

/* ### Modal Class ###
 * Author: Guilherme Serrano
 * Using jQuery
 *
 * ### How to ###
 * var name = new Modal(name, mask)
 *
 * # Arguments #
 * name = id único
 * mask (true/false) = using mask
 *
 * All links with rel="name" will open modal box
 *
 */
function Modal(modalName,mask){
	//Vars
	maxHeight = 450;
	maxWidth = 650;
	thisClass = this;
	//Initialize modal
	this.initialize = function(){
		//Create elements & vars
		if($("#"+modalName).size() < 1){
			$("body").append("<div id="" + modalName + ""></div>")
		}
		divModal = $("#"+modalName);
		divModal.addClass("modal");
		var content = divModal.html();
		divModal.html("");
		divModal.prepend("<div class="modal_top"><a href="#" title="Fechar esta janela" id="" + modalName +"_close">Fechar</a></div><div class="modal_content"></div>");
		$("#"+modalName +" .modal_content").html(content);
		//Mask
		if(mask){
			if ($("#divMask").size() < 1) {
				divMask = "<div id="divMask" style="height:" + $(document).height() + "px;"></div>";
				$(divMask).appendTo("body");
			}
		}
		//Close button
		$("#"+modalName +"_close").click(function(){
			thisClass.close();
		});
		divContent = $("#"+modalName +" .modal_content");
		//Centralize on resize window
		$(window).bind("resize", function() {
			thisClass.centralize();
		});
		//Open buttons
		$("a[rel=""+modalName+""]").click(function(){
			href = $(this).attr("href")
			if(href == null || href == "" || href == "undefined" || href == "#"){
				thisClass.open();
			}else{
				thisClass.open(href)
			}
			return false;
		})
	}
	//Open
	this.open = function(content){
		thisClass.setContent(content);
		if (mask) {
			thisClass.showElement("#divMask");
		}
		thisClass.showElement("#"+modalName);
		thisClass.setMeasures();
	}
	//Close
	this.close = function(){
		if(mask){
			thisClass.hideElement("#divMask");
		}
		thisClass.hideElement("#"+modalName);
	}
	//Load content
	this.setContent = function(content){
		if(content != undefined && content != null && content != ""){
			if(content.match(/.gif/) || content.match(/.jpg/) || content.match(/.jpeg/) || content.match(/.png/)){
				divContent.html("<img src=""+content+"" />");
			}else if(content.match(/http:///) || content.match(/https:///) || content.match(/file:///)){
				divContent.load(content, null, thisClass.setMeasures);
			}else{
				divContent.html($(content).html());
			}
		}
	}
	//Show
	this.showElement = function(e){
		$(e).show();
	}
	//Hide
	this.hideElement = function(e){
		$(e).hide();
	}
	//Centralize
	this.centralize = function(){
		var posTop = (($(window).height()/2) - (divModal.height()/2))
		var posLeft = (($(window).width()/2) - (divModal.width()/2))
		divModal.css({
			"top" : posTop + "px",
			"left" : posLeft + "px"
		});
	}
	this.setMeasures = function(){
		thisClass.setWidth();
		thisClass.setHeight();
		thisClass.centralize();
	}
	// Set height
	this.setHeight = function(){
		h = divContent.height()
		if(h > maxHeight){
			divContent.css({
				"height": maxHeight+"px"
			})
			divModal.css({
				"height": (maxHeight+50)+"px"
			})
		}else{
			divModal.css({
				"height": "auto"
			})
		}
	}
	this.setWidth = function(){
		w = divContent.width()
		if(w > maxWidth){
			divModal.css({
				"width": (maxWidth+20)+"px"
			})
		}else{
			divModal.css({
				"width": "auto"
			})
			if(divContent.width() > maxWidth){
				//alert("Deixou auto, ficou maior, reduziu!")
				divModal.css({
					"width": (maxWidth+20)+"px"
				})
			}
		}
	}
}

E o CSS

.modal {
	position: absolute;
	z-index: 99999;
	display: none;
	background: #fff;
	border: 2px solid #777;
}
.modal_content{
	border: 1px solid #333;
	margin: 5px;
	padding: 5px;
	overflow: auto;
	_height: expression(this.height > 450 ? 450: true);
	max-height: 450px;
}
.modal_content div{
	border: 2px solid blue;
	height: auto;
}
#divMask {
	background-color:#000;
	width: 100%;
	left:0px;
	margin:0px;
	padding:0px;
	position:absolute;
	top:0px;
	z-index:1000;
	opacity:0.8;
	filter:alpha(opacity=80);
	display: none;
}

 

Como fiz a classe para estudos não utilizei nenhuma imagem e estou publicando sem formatar bonitinho o header do modal (botão para fechar).

 

Como utilizar

O uso ficou bastante simples, é só iniciar o modal e criar os links que devem abrir. Segue um exemplo da criação de um modal chamado "modal":

 

$(document).ready(function(){
	var modal = new Modal("modal",true)
	modal.initialize();
});

O código acima acessa a função "initialize" da classe, o primeiro parâmetro (modal) é o nome do seu modal, que pode ser qualquer um. O segundo parâmetro (true) é um boolean, e define se será utilizado a mask para escurecer o fundo do site e destacar apenas o modal ou não.

Os links devem ter o atributo rel igual ao nome do modal que você iniciou (no exemplo de cima, rel="modal") e o atributo href indica qual o conteúdo será exibido no modal (pode ser link externo, link para imagem ou o id de algum elemnto da página atual.

 

<a href="#" rel="modal">Open modal</a><br />
<a href="http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif" rel="modal">Open external image</a><br />
<a href="#content" rel="modal">Open div#content content</a><br />
<a href="https://andafter.org/" rel="modal">Open external page</a><br />

 

Conclusão

Gostei da brincadeira, o tempo de desenvolvimento não fui muito longo, comecei no trabalho e terminei em casa, depois fiz alguns ajustes. A biblioteca jQuery é realmente mágica, o código estava bastante curto, pouquíssimas linhas e um modal funcionando.

O código aumentou na medida que comecei a adiconar funcionalidade (identificar o tipo de conteúdo, criar automaticamente as actions para os links com o atributo rel, redimensionar e reposicionar o modal quando a janela é aberta, etc…)

No IE ainda ficou a pendência de fazer o modal diminuir a altura.

Novidades do PHP 5.3

A pouco tempo renovei diversos feeds da minha aba "Desenvolvimento", adicionei alguns muito bons focados em interface, eliminei alguns blogs estagnados e ao pouco estou acompanhando a galerinha do PHP desde que deixei o ASP de lado e voltei a brincar com o PHP.

Infelizmente estou estudando PHP bem menos que gostaria (em compensação meu estudo com Javascript e jQuery vai à pampa!*), mas aos poucos estou aprendendo e nada melhor do que acompanhar a galera que manja para isso!

PHP

Já peguei algumas aulas com o Chris que também está fazendo testes com o framework Code Igniter (que comecei a utilizar por dica do Furst), mas sei que deveria estudar sintaxe antes de brincar com frameworks. Mas quem desenvolve sabe, a afobação é inevitável e ver as coisas funcionando é muito mais legal! 😀

 

Novidades do PHP 5.3

Apresentação do Felipe Ribeiro no PHP – Paraíba.

 

Apesar de não saber (ainda) como funcionavam (ou se existiam) algumas coisas nas versões anteriores, fiquei feliz com algumas coisas que li, como os slides "lambdas e closures", que lembraram bastante algumas coisas do javascript.

 

E aos que desenvolvem em PHP fica minha recomendação do blog do Felipe.

 


* à pampa – satisfeito, ótimo, bom demais.

Primeira experiência com Prototype

 

Eu conhecia a biblioteca de javascript Prototype apenas por documentação e leitura dos posts que o Chris fez por aqui (um passo a passo bem bacana para iniciar o uso da biblioteca), mas até esta semana nunca utilizado ela de verdade.

Comecei a colocar a mão (ui) em um projeto aqui da MMCafé que utiliza a biblioteca, portanto precisei aprender alguma cois, e resolvi documentar minha experiência inicial.

 

Primeiras impressões sobre Prototype

A biblioteca é bacana, mas aparentemente bem mais complexa que jQuery. Segundo o Chris jQuery tem muitas "funções mágicas", o que pode levar ele a ser menos performático. Não sei, não posso opinar, mas admito que tais funções mágicas facilitam a vida em muitos casos! 😀

Ah, essa complexidade pode ser apenas um medo inicial (sair da zona de conforto, né?), então não quero assustar ninguém. Achei a documentação bem boa, mas senti um pouco de falta de alguns exemplos na documentação – nada que uma googleada e alguns blogs não resolvessem.

 

Seletores

Não vou explicar o funcionamento dos seletores, o post é para expor minha opinião apenas. Para quem conhece jQuery, os seletores funcionam de forma parecida com o jQuery , então achei bastante fácil.

 

Elements, observe, objects

Sofri! Demorei bem mais tempo do que eu esperava para fazer algumas coisas simples, como setar ações onclick em elementos de determinada classe.

Nesta curta experiência o que me fez sofrer mesmo foi a forma como o Prototype trabalha com os eventos. Aos leitores desenvolvedores (ou apenas curiosos e entusiastas) tenho um post saindodo forno que explica e exemplifica meu problema e minha solução para setar a ação em uma classe inteira de links.

 

Resumo da obra

Ainda sou mais jQuery pois já estou familiarizado com seus seletores, manipulação de elementos, etc. Também gosto pelo fato da documentação e os diversos blogs com plugins e exemplos de códigos (mas isso não posso comparar pois não procurei blogs específicos sobre Prototype, eles devem existir).

jQuery logo

 

A Prototype não é o bixo de sete cabeças que eu temia, achei a documentação boa, e acredito que a produtividade poder ser equivalente a do jQuery – para quem já conhece o funcionamento da biblioteca e não precisa ficar consultando a documentação a cada 5 minutos, claro.

Continuo achando jQuery mais interessante, mas depois dessa curta experiência estou vendo a Prototype com melhores olhos. 🙂

 

Recomendo a leitura

Aí vai uma seleção de posts sobre Prototype já publicados por aqui, quase todos do Chris:

 

Comparação entre a jQuery e a Prototype

Usando a Prototype – passo 4 – upload de arquivo sem post na tela

Usando a prototype – passo 8 – seletores CSS

Usando a Prototype – passo 3 – arrays e a classe Enumerable

Criar classes em javascript – usando a Prototype

 

 

E você, o que prefere?
Prototype, jQuery ou outra biblioteca? Quais os motivos?

Compartilhe sua opinião nos comentários 😉

Usando o trigger da jQuery

Esse método já me salvou a vida algumas vezes – com ele é possível disparar um evento de um (ou mais) elementos sem que haja a interacão do usuário.

Por exemplo, imagine o seguinte html:

<select id="meu_select">
   <option value="SP">São Paulo</option>
   <option value="RJ">Rio de Janeiro</option>
   <option value="RS">Rio Grande do Sul</option>
</select>

Com a seguinte implementação javascript (usando jQuery):

$("select#meu_select").change(function() {
   //faz alguma coisa aqui, como uma requisição assíncrona por exemplo
});

Simples, não? Sempre que houver uma mudança no select, será chamadop o bloco de código dentro do change()
Agora, e se você quiser a qualquer ponto do fluxo chamar esse change(), ou simular que o usuário fez uma seleção? Por exemplo, quando a página carrega, você já quer chamar esse bloco para que algo aconteça.
Existe um método no jQuery, trigger, com o qual você pode resolver isso. Simples assim:

$("select#meu_select").trigger("change");

Nesse caso, o método change do elemento select#meu_select é disparado, sem precisar de outras interferências.

Para mais detalhessobre o método e outras formas de usá-lo, visite a documentação oficial.

Plugin de jQuery para criar QR Code

Navegando e aprendendo coisas novas, enquanto estudava seletores customizáveis com jQuery encontrei posts interessantes também para a criação de QR Code com jajavasript, e a criação de um "plugin" (se assim se pode chamar, devida a simplicidade) do jQuery para criação do QR Code.

 

O que é QR Code?

Se você já sabe o que é QR Code pule essa parte, é apenas uma explicação simples para entender o conceito:

O QR Code (ou Código de Barras em 2D), é uma matriz ou código de barras bi-dimensional, criado pela empresa Japonesa Denso-Wave, em 1994. O QR vem de Quick Response, pois o código pode ser interpretado rapidamente, mesmo com imagens de baixa resolução, feitas por cameras digitais em formato VGA, como as de celulares. O QR Code é muito usado no Japão.

Wikipedia pt

 

O QR Code permite que você fotografe com um celular um código e acesse automaticamente uma URL, por exemplo. O funcionamento é idêntico ao do código de barras, mas até onde sei código de barras é traduzido apenbas em números, enquanto o QR Code permite passar urls completas 😀

 

 

Como gerar QR Code com javascript?

Na verdade não vamos codificar uma URL em imagem QR Code, vamos utilizar geradores prontos e utilizar o javascript como ferramenta para solicitar a geração do QR Code e exibir essa imagem em nosso site ou aplicativo web.

 

 

$(document).ready(function(){

        // Vamos criar um plugin do jquery chamado qrcode

        (function ($) { 

          $.fn.qrcode = function(url,size) { 

                return "http://chart.apis.google.com/chart?cht=qr&chl=" + urk +"&chs=" + size +"x" + size

          }

        })(jQuery);

        $("body").append("<img src=""+$().qrcode("https://andafter.org", "100")+"">");

});

 

 

No exemplo acima utilizamos o google para criar o QR Code e é possível escolher o tamanho da imagem (variável size da função).

Mais serviços que criam QR Codes e podem ser utilizados no plugin:

http://go.bath.ac.uk/qr/download?DATA=https://andafter.org

http://qrcode.kaywa.com/img.php?s=100&d=https://andafter.org

 

 

É isso, espero ter ajudado! 🙂

 

Leia mais