Criando um Plugin de Marca D’água com jQuery
Neste tutorial você irá aprender a criar um plugin para jQuery que insere uma marca d’água em inputs do tipo text e textarea.
O primeiro passo é criar um arquivo javascript. Uma sugestão de nome é jquery.{nome do plugin}.js, então no meu caso vou nomear o arquivo jquery.watermark.js.
Várias bibliotecas/frameworks de javascript dão ao símbolo $ uma função especial, e isotp não é diferente para jQuery, então o primeiro passo é evitar que este conflito ocorra. Para isso devemos iniciar nosso plugin com uma função anônima autoexecutável, passando o parâmetro jQuery e transformando-o em $, como no código abaixo.
(function($){
//Todo o código que compõe o plugin deve ficar aqui.
})(jQuery);
Em seguida devemos mencionar que estamos iniciando um plugin, então escrevemos o seguinte
(function($){
$.fn.watermark = function(){
//Aqui vem os parâmetros e as funções que compõem o plugin.
}
})(jQuery);
Agora devemos decidir se nosso plugin terá parâmetros ou não. Neste caso eu adicionarei alguns parâmetros, são eles:
- corMarcaDagua
- estiloMarcaDagua
- corTexto
- estiloTexto
- valorPadrao
estes parâmetros me darão a cor e o estilo da marca d’água, a cor e o estilo do texto que é digitado, e o valor padrão do input ou textarea que não tiver valor especificado.
(function($){
$.fn.watermark = function(parametros){
//Aqui vem os parâmetros e a funções que compõem o plugin.
}
})(jQuery);
A variável parâmetros será um objeto passado para o plugin. Caso o usuário não passe nenhum valor o plugin deve estar preparado para usar valores padrões, por isso crio um objeto que será usado para este fim.
(function($){
$.fn.watermark = function(parametros){
var padroes = {
corMarcaDagua : '#bbbbbb'
,estiloMarcaDagua : 'italic'
,corTexto : '#000000'
,estiloTexto : 'normal'
,valorPadrao : 'pesquisar...'
}
//O plugin continua aqui...
}
})(jQuery);
O plugin deve usar os valores padrões caso o usuário não passe nenhum valor, mas caso seja passado o plugin deve usar os valores do usuário. Para isto acontecer devemos estender os valores padrões e mescla-los com os valores do usuário. Abaixo vê-se como criar chegar a este fim
function($){
$.fn.watermark = function(parametros){
var padroes = {
corMarcaDagua : '#bbbbbb'
,estiloMarcaDagua : 'italic'
,corTexto : '#000000'
,estiloTexto : 'normal'
,valorPadrao : 'pesquisar...'
}
padrao = $.extend({},padroes,parametros);
//O plugin continua aqui...
}
})(jQuery);
A função $.extend() tem 3 parâmetros. O primeiro é um objeto vazio, o segundo é a variável com os padrões do plugin, e o terceiro é o objeto passado pelo usuário. Repare como a variável padrao agora se torna os parâmetros que o usuário passar, ou assume os valores padrões que criamos, caso o usuário não passe nada.
O próximo passo é criar a(s) função(s) que deve ser executada para CADA(each) elemento que for atingido com o seletor de jQuery.
(function($){
$.fn.watermark = function(parametros){
var padroes = {
corMarcaDagua : '#bbbbbb'
,estiloMarcaDagua : 'italic'
,corTexto : '#000000'
,estiloTexto : 'normal'
,valorPadrao : 'pesquisar...'
}
padrao = $.extend({},padroes,parametros);
return this.each(function(){
//Todos os elementos que forem atingidos com
//o seletor do jQuery sofrerão com o que vier
//aqui dentro.
});
}
})(jQuery);
Repare que usei return antes de this.each(). Isto não é estritamente necessário, mas é altamente recomendável, para que nosso plugin permita chaining no jQuery.
No começo eu disse que o plugin seria limitado a inputs do tipo texto e textarea, porém o plugin ainda não sabe da minha intenção, então tenho que dizer explicitamente que quero isso. em jQuery usamos o método is() para descobrir com qual elementos estamos trabalhando.
(function($){
$.fn.watermark = function(parametros){
var padroes = {
corMarcaDagua : '#bbbbbb'
,estiloMarcaDagua : 'italic'
,corTexto : '#000000'
,estiloTexto : 'normal'
,valorPadrao : 'pesquisar...'
}
padrao = $.extend({},padroes,parametros);
return this.each(function(){
if($(this).is('input:text') || $(this).is('textarea') ){
//Aqui ficarão as ações que serão executadas
//em todos os input's e textarea's que forem
//atingidos com nosso seletor de jQuery
}
});
}
})(jQuery);
Repare que filtrei os inputs do tipo texto somente escrevendo ‘:text’, mas eu poderia alternativamente usar a sintaxe de CSS input[type=text].
até este momento usei o elemento $(this) mais de uma vez, então é uma boa ideia usar uma variável que tenha o mesmo valor dele, para armazena-lo em cache e tornar nosso script mais rápido. Vou chamar a variável de $elemento, para ficar claro que ele representará cada elemento. Também coloco um cifrão no começo, para que fique claro que estou mexendo com um objeto do jQuery.
(function($){
$.fn.watermark = function(parametros){
var padroes = {
corMarcaDagua : '#bbbbbb'
,estiloMarcaDagua : 'italic'
,corTexto : '#000000'
,estiloTexto : 'normal'
,valorPadrao : 'pesquisar...'
}
padrao = $.extend({},padroes,parametros);
return this.each(function(){
$elemento = $(this);
if($elemento.is('input:text') || $elemento.is('textarea') ){
//Aqui ficarão as ações que serão executadas
//em todos os input's e textarea's que forem
//atinigidos com nosso seletor de jQuery
}
});
}
})(jQuery);
Quando iniciamos o plugin queremos que o valor padrão que aparece nos input’s e textarea’s esteja na forma de marca d’água, então devemos dar a ele a cor de marca d’água e o estilo de marca d’água. Para isso usamos o método css() em todos os elementos usando a variável $elemento.
(function($){
$.fn.watermark = function(parametros){
var padroes = {
corMarcaDagua : '#bbbbbb'
,estiloMarcaDagua : 'italic'
,corTexto : '#000000'
,estiloTexto : 'normal'
,valorPadrao : 'pesquisar...'
}
padrao = $.extend({},padroes,parametros);
return this.each(function(){
$elemento = $(this);
if($elemento.is('input:text') || $elemento.is('textarea') ){
$elemento.css({
color : padrao.corMarcaDagua
,fontStyle: padrao.estiloMarcaDagua
});
}
});
}
})(jQuery);
Em seguida temos de descobrir uma maneira de guardar os valores padrões dos input’s e textarea’s. Escolhi guarda-lo no atributo rel, que será criado dinamicamente com o script.
Caso o input tenha um valor no HTML, o usaremos, caso contrário usaremos o que será passado ao plugin pelo usuário, se nada for passado usaremos o padrão do plugin(‘pesquisar…’).
(function($){
$.fn.watermark = function(parametros){
var padroes = {
corMarcaDagua : '#bbbbbb'
,estiloMarcaDagua : 'italic'
,corTexto : '#000000'
,estiloTexto : 'normal'
,valorPadrao : 'pesquisar...'
}
padrao = $.extend({},padroes,parametros);
return this.each(function(){
$elemento = $(this);
if($elemento.is('input:text') || $elemento.is('textarea') ){
$elemento.css({
color : padrao.corMarcaDagua
,fontStyle : padrao.estiloMarcaDagua
});
vall = ($elemento.val() != '')?$elemento.val():padrao.valorPadrao;
$elemento.val(vall).attr('rel',vall);
//O plugin continua aqui...
}
});
}
})(jQuery);
Repare que o que vem após vall =(linha 25) nada mais é do que um if/else no modo compacto. O que vem antes da interrogação é a condição. o que vem entre os dois pontos e a interrogação é o valor retornado se a condição for verdadeira, e o que q vem depois dos dois pontos é o valor retornado se a condição for falsa. Nesse caso vall vai ser igual ao valor do elemento que está no HTML caso haja algum valor ($element.val() é diferente de vazio), e vall será igual ao valor passado pelo usuário ou o valor padrão do plugin, caso nenhum valor seja passado direto no HTML. Na linha 27 esse valor é passado para o elemento, e em seguida para o atributo rel.
Agora devemos criar a parte onde indicamos o que deve ocorrer quando o usuário entra ou sai do input/textarea. Primeiro vou criar a parte que indica o que deve ocorrer quando o usuário ENTRA no input/textarea.
Para não ficar reescrevendo todo o script, vou mostrar somente a parte onde há a interação com os elementos. Para indicar a ação de entrada no input/textarea usamos o evento focus, e nesta entrada executamos uma função.
$elemento.focus(function(){
});
Quando estamos dentro do focus o $(this) indica o elemento quando está entrando em foco, então não podemos confundir com o $(this) usado anteriormente. Para facilitar o entendimento vou criar uma variável chamada $elementoEmFoco e direciona-la ao $(this).
$elemento.focus(function(){
$elementoEmFoco = $(this);
});
Quando entramos no input/textarea sempre haverá um valor assinalado (no tutorial em vídeo não me atentei a este detalhe, e acabei escrevendo uma parte redundante no código), e estamos seguros disto pois quando escrevermos o código para quando o cursor sair do input/textarea colocaremos um valor no mesmo. Então quando entramos queremos ter a cor e o estilo do texto do usuário, o que é criado nas linhas 3-6
$elemento.focus(function(){
$elementoEmFoco = $(this);
$elementoEmFoco.css({
color:padrao.corTexto
,fontStyle:padrao.estiloTexto
});
});
Por fim, se quando entrarmos no elemento ele tenha o valor igual ao que foi guardado no atributo rel, queremos que esse valor desapareça e que o input/textarea fique vazio, para que o usuário possa digitar seu texto.
$elemento.focus(function(){
$elementoEmFoco = $(this);
$elementoEmFoco.css({
color:padrao.corTexto
,fontStyle:padrao.estiloTexto
});
if($elementoEmFoco.val() == $elementoEmFoco.attr('rel')){
$elementoEmFoco.val('');
}
});
Terminada a ação executada quando entramos no input/textarea temos de criar a ação que será executada quando sairmos do mesmo. Para isso usamos o método blur(). Inicialmente faremos o mesmo que fizemos anteriormente, executaremos uma função assim que sairmos do input/textarea, e criaremos uma variável que será igual ao $(this), que neste caso indica o elemento quando está saindo de foco.
$elemento.blur(function(){
$elementoForaDeFoco = $(this);
});
Se quando sairmos do input/textarea seu valor seja igual a vazio ou seu valor seja igual ao valor do atributo rel, queremos que ele seja tratado como uma marca d’água, então ele deve ter a cor e o estilo da marca d’água.
$elemento.blur(function(){
$elementoForaDeFoco = $(this);
if($elementoForaDeFoco.val() == '' || $elementoForaDeFoco.val() == $elementoForaDeFoco.attr('rel')){
$elementoForaDeFoco.css({
color : padrao.corMarcaDagua
,fontStyle : padrao.estiloMarcaDagua
});
}
});
Além disso queremos que o valor volte a ser o valor padrão do input/textarea caso o mesmo esteja vazio ou tenha o valor igual ao valor do atributo rel, então incluimos uma linha de código dentro do if.
$elemento.blur(function(){
$elementoForaDeFoco = $(this);
if($elementoForaDeFoco.val() == '' || $elementoForaDeFoco.val() == $elementoForaDeFoco.attr('rel')){
$elementoForaDeFoco.css({
color : padrao.corMarcaDagua
,fontStyle : padrao.estiloMarcaDagua
});
$elementoForaDeFoco.val($elementoForaDeFoco.attr('rel'));
}
});
O plugin termina aqui. Farei somente uma modificação no código, que é inicializar todas as variáveis no início do documento. Esta prática não é estritamente necessária, porém particularmente eu gosto de fazer assim. A seguir está todo o plugin, incluindo essas modificações que fiz.
(function($){
$.fn.watermark = function(parametros){
var padrao
,vall
,$elemento
,$elementoEmFoco
,$elementoForaDeFoco
,padroes = {
corMarcaDagua : '#bbbbbb'
,estiloMarcaDagua : 'italic'
,corTexto : '#000000'
,estiloTexto : 'normal'
,valorPadrao : 'pesquisar...'
}
padrao = $.extend({},padroes,parametros);
return this.each(function(){
$elemento = $(this);
if($elemento.is('input:text') || $elemento.is('textarea') ){
$elemento.css({
color : padrao.corMarcaDagua
,fontStyle: padrao.estiloMarcaDagua
});
vall = ($elemento.val() != '')?$elemento.val():padrao.valorPadrao;
$elemento.val(vall).attr('rel',vall);
$elemento.focus(function(){
$elementoEmFoco = $(this);
$elementoEmFoco.css({
color:padrao.corTexto
,fontStyle:padrao.estiloTexto
});
if($elementoEmFoco.val() == $elementoEmFoco.attr('rel')){
$elementoEmFoco.val('');
}
});
$elemento.blur(function(){
$elementoForaDeFoco = $(this);
if($elementoForaDeFoco.val() == '' || $elementoForaDeFoco.val() == $elementoForaDeFoco.attr('rel')){
$elementoForaDeFoco.css({
color : padrao.corMarcaDagua
,fontStyle : padrao.estiloMarcaDagua
});
$elementoForaDeFoco.val($elementoForaDeFoco.attr('rel'));
}
});
}
});
}
})(jQuery);
O plugin ,do jeito que está, tem 1565 bytes de tamanho, o que em princípio é considerado pequeno, porém é sempre uma boa ideia diminuir o máximo possível o tamanho dos arquivos que serão incluídos nas páginas. O próprio framework jQuery apresenta uma versão minimizada.
Para criar essa versão usarei um compressor chamado YUI Compressor. Este compressor comprimi arquivos de javascript e CSS. O primeiro passo é baixar o compressor, e para isso você deve ir à página de download e baixa-lo. Baixei a única versão disponível na data de criação deste tutorial 2.4.2.
Primeiro você deve extrair a pasta zipada para uma pasta de sua escolha, eu escolhi a pasta que meu plugin está. Em seguida você deve jogar o plugin pra dentro da pasta build, que está dentro da pasta yuicompressor-x.y.z(no meu caso x=2, y=4 e z=2). Eu não gosto de jogar meu arquivo diretamente, eu faço uma cópia e coloco a mesma lá dentro, para evitar que, por qualquer motivo, meu arquivo seja danificado.

Para executar o compressor você deve acessar a pasta onde os arquivos estão localizados, o modo mais simples é copiando o endereço (no meu caso é o destacado na imagem acima). Agora você deve abrir o prompt de comando, caso você esteja usando Windows vá em Iniciar>Executar(start>Run) , digite cmd e pressione ok.

Um prompt de comando surgirá na tela. digite cd “{endereço do arquivo em java e plugin}”, incluindo as aspas e pressione Enter. no meu caso digitarei:
cd "C:\Users\Eduardo\My Documents\Aptana Studio Workspace\watermark\yuicompressor-2.4.2\build"
Neste momento você deve estar na pasta onde seus arquivos estão. para criar o arquivo comprimido do plugin executamos o seguinte comando: java -jar {nome do arquivo em java da pasta}.jar {nome do arquivo a ser comprimido}.js -o {nome do arquivo de saída}.js. No meu caso ficou da seguinte maneira
java -jar yuicompressor-2.4.2.jar jquery.watermark.js -o jquery.watermark.min.js
Em poucos instantes um arquivo é criado na pasta, chamado jquery.watermark.min. O tamanho dele é 679 bytes, 56,6% menor que o arquivo original. Mas tome CUIDADO para não descartar o arquivo original! Sempre que você quiser modificar seu plugin, é nele que você vai mexer, e no fim você comprimi dinovo.
Para testar o seu plugin crie uma página em HTML como a seguinte
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
input,textarea{display:block;}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Watermark Plugin</title>
</head>
<body>
<input type="text" />
<input type="text" value="nome"/>
<input type="text" value="email"/>
<textarea rows="7" cols="25">Digite sua mensagem</textarea>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="jquery.watermark.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('input,textarea').watermark();
});
</script>
</body>
</html>
Não se esqueça que o arquivo minimizado deve estar na mesma página do documento em HTML para que o endereço do atributo src, e também não esqueça que o framework jQuery deve ser adicionado antes de todos os arquivos que contenham jQuery. Nesse caso em específico adicionei os scripts no fim da página(imediatamente antes do término do body), mas poderia ter sido no head.
Para executar o plugin selecionei todos os input’s e textarea’s da página (poderia selecionar somente uma parte) e executei o comando watermark(). Você pode modificar os valores padrões, e para isso basta escrever o objeto como parâmetro, da seguinte maneira
$(document).ready(function(){
$('input,textarea').watermark({
corMarcaDagua:'#abc'
,estiloMarcaDagua:'normal'
,corTexto:'green'
,estiloTexto:'italic'
,valorPadrao:'digite seu texto...'
});
});
Abra a página novamente e teste. Você verá que os estilos foram mudados, além do texto marca d’água que aparece nos input’s/textarea’s que não tem valor. Você não é obrigado a passar todos os valores, mas somente aqueles que interessam ser mudados.
Você pode testar o resultado final, ou baixar os arquivos, nos links abaixo:
sandalye • 16/09/2009
tnahk you admin; perfect code