1 (function(){
   2 /**
   3  * jProton JavaScript Framework, version 0.3.0a
   4  * Copyright (c) 2008 Pedro Simonetti Garcia
   5  * 
   6  * Version - 0.3.0a
   7  * $Revision: 238 $
   8  * $Date: 2008-03-25 07:57:54 -0300 (ter, 25 mar 2008) $
   9  * 
  10  * Project site: http://code.google.com/p/jproton/
  11  * Licensed under MIT: http://www.opensource.org/licenses/mit-license.php
  12  */
  13 
  14 /**
  15  * Namespace central do framework. "jProton" é um namespace executável, de modo
  16  * que ele é tanto um agregador de métodos/atributos quanto uma função. Como
  17  * namespace, ele é o agregador de todas funcionalidades do framework. Como
  18  * função, ele é um atalho para o principal recurso do framework: a seleção de
  19  * elementos do "documento". Além disso, o namespace "$" é um atalho para 
  20  * "jProton", de modo que os dois códigos abaixo:
  21  * 
  22  * ~~
  23  * // Usa o namespace jProton para instanciar a classe jProton.Set
  24  * jProton(selector, context)
  25  * // Usa o atalho $ para instanciar a classe jProton.Set
  26  * $(selector, context)
  27  * ~~
  28  * 
  29  * equivalem a:
  30  * 
  31  * ~~
  32  * // Instancia uma nova classe jProton.Set explicitamente 
  33  * new jProton.Set().select(selector, context)
  34  * ~~
  35  * 
  36  * A maioria dos recursos do framework encontram-se dentro de outros namespaces
  37  * dentro de "jProton", como "jProton.Set", ou "jProton.ajax". Mas, alguns 
  38  * recursos especiais encontram-se no próprio namespace "jProton", como os 
  39  * métodos "jProton.trim"() e "jProton.each"(), acessíveis também como 
  40  * "$.trim()" e "$.each()".
  41  *  
  42  * @name jProton
  43  * @namespace
  44  * @extends core
  45  *//** @ignore */
  46 window.jProton = function(selector, context) {
  47   return new jProton.Set().select(selector, context);
  48 };
  49 
  50 /** 
  51  * Atalho para o namespace "jProton". Considerando que "jProton" é um 
  52  * namespace executável, ou seja, ele é um namespace e função ao mesmo tempo,
  53  * o atalho "$" pode ser usado para ambos os casos. Ou seja, é possível usá-lo 
  54  * como namespace para acessar recursos do framework, como a método "$.trim()", 
  55  * o namespace "$.ajax", ou a classe "$.Set". É possível também usá-lo como 
  56  * função, no formato "$()", o que consiste no atalho para instanciar uma 
  57  * classe "jProton.Set".
  58  * 
  59  * @function
  60  * @name $
  61  * @param {String}  selector  Seletor usado para selecionar os elementos.
  62  * @param {Element} [context] Contexto usado na busca. O padrão é "document".
  63  * @return {jProton.Set}
  64  * @see jProton
  65  * @extends core 
  66  */
  67 window.$ = jProton;
  68 
  69 
  70 /**
  71  * Cria um namespace, e retorna o último objeto desse namespace.
  72  * 
  73  * *Exemplo:*
  74  * ~~
  75  * // Cria o namespace 'my.name.space' caso não exista, e retorna o último 
  76  * // objeto do namespace, no caso o objeto 'space'.
  77  * $.namespace('my.name.space');
  78  * ~~
  79  * 
  80  * @function
  81  * @param {Object}  ns   Namespace a ser criado.
  82  */
  83 jProton.namespace = function(ns) {
  84   if (!ns)
  85     return;
  86 
  87   var n = ns.split('.');
  88   var target = window, o;
  89   
  90   for (var i = 0, ni; ni = n[i]; i++) {
  91     target = (o = target[ni]) ? o : target[ni] = {};
  92   }
  93 
  94   return target;
  95 };
  96 
  97 
  98 /**
  99  * Extende as propriedades de um ou mais objetos-fonte para outro objeto-alvo. 
 100  * Se apenas um objeto for passado como parâmetro, ele será considerado o
 101  * objeto-fonte, e o objeto referenciado por "this" será considerado o alvo,
 102  * que nesse caso será o namespace "jProton". Se mais de um objeto for
 103  * passado como parâmetro, o primeiro objeto será considerado o alvo, e os 
 104  * objetos restantes serão considerados as fontes.
 105  * 
 106  * Ao final, será retornado o objeto-alvo extendido.
 107  * 
 108  * ===Sintaxe:===
 109  * ~~
 110  * jProton.extend( source || ( target, source1 [ , source2, ... ] ) );
 111  * ~~
 112  * 
 113  * Existem três propriedades que possuem significado especial quando 
 114  * definidas no objeto fonte. Elas são: "@init", "@extension" e "@require".
 115  * Essas propriedades não serão extendidas para o objeto alvo, servindo apenas
 116  * para definir respectivamente a inicialização, registro e dependência da 
 117  * extensão.
 118  * 
 119  * *NOTA: A maneira de declarar as extensões e suas dependências será 
 120  * diferente na versão 0.4.x, e por consequência, as propriedades
 121  * "@extension" e "@require" entrarão em desuso.*
 122  * 
 123  * ==Inicialização de Extensões==
 124  * 
 125  * Algumas extensões necessitam que um determinado código seja executado 
 126  * assim que a extensão for criada. Para isso, deve-se informar no objeto
 127  * fonte a ser inicializado a propriedade especial "@init", com a devida
 128  * função de inicialização como seu valor.
 129  * 
 130  * ==Registro de Extensões==
 131  * 
 132  * Além disso, o método "jProton.extend()" pode ser usado também para registrar 
 133  * extensões automaticamente. Para isso, deve-se informar uma propriedade 
 134  * especial no objeto fonte com nome "@extension". O valor dessa propriedade é 
 135  * um objeto que especifica o nome e versão da extensão, no seguinte formato:
 136  * 
 137  * ~~
 138  *   '@extension': {'name': 'version'}
 139  * ~~
 140  * 
 141  * O registro é feito definindo uma propriedade com nome "name" e valor 
 142  * "version" no namespace "extensions" do objeto alvo. Repare que se um
 143  * namespace for informado como alvo, a extensão será registrada no último
 144  * objeto do namespace, como exemplificado abaixo:
 145  * 
 146  * ~~
 147  *   target.namespace.extensions.name = 'version';
 148  * ~~
 149  * 
 150  * 
 151  * ==Dependência de Extensões==
 152  * 
 153  * Se a extensão que está sendo criada usa recursos de uma outra extensão,
 154  * deve-se usar a propriedade especial "@require" para a dependência com
 155  * outra extensão, evitando assim que a extensão seja carregada caso a
 156  * extensão requirida não esteja instalada.
 157  * 
 158  * Se a extensão requerida não estiver instalada, será gerado um erro 
 159  * indicando que a extensão deve ser instalada. Se a extensão requerida 
 160  * estiver instalada, mas for de uma versão inferior a versão requerida, 
 161  * será gerado um erro indicando a versão instalada é inferior a versão
 162  * requerida.
 163  * 
 164  * O exemplo a seguir ilustra o uso das três propriedades especiais para
 165  * se criar uma extensão de "jProton". Será criada a extensão "myExt" versão
 166  * "0.1" no namespace "jProton.myPlugin" apenas se a extensão "myOtherExt" 
 167  * versão "0.2" já estiver instalada em "jProton.myPlugin". Se a extensão
 168  * requerida estiver instalada, será criado o namespace "jProton.myPlugin", 
 169  * e adicionado a ele a propriedade "newProperty" e o método "newMethod". Além 
 170  * disso, como esta sendo informado a propriedade "@extension", será criada 
 171  * uma nova propriedade "jProton.myPlugin.extensions.myExt" com o valor "0.1". 
 172  * Ao final, será retornado o objeto alvo raiz, no caso, o objeto "jProton".
 173  * 
 174  * *Exemplo 2:*
 175  * ~~
 176  * // Cria o namespace onde do plugin
 177  * $.namespace('jProton.myPlugin');
 178  * 
 179  * // Cria uma nova extensão no namespace 'jProton.myPlugin'. Será criada
 180  * // uma nova propriedade 'jProton.myPlugin.extensions.myExt' com o valor
 181  * // '0.1' indicando o registro e versão da extensão.
 182  * $.extend(jProton.myPlugin, {
 183  * 
 184  *   // declara a dependência com outra extensão
 185  *   '@require': {'myOtherExt': '0.2'},
 186  *   
 187  *   // registra a extensão  
 188  *   '@extension': {'myExt': '0.1'},
 189  *   
 190  *   // Função de inicialização
 191  *   '@init': function() {
 192  *     // O código de inicialização segue aqui
 193  *     ...
 194  *   },
 195  *    
 196  *   // nova propriedade a ser extendida
 197  *   newProperty: 'value',
 198  *    
 199  *   // novo método a ser extendido
 200  *   newMethod: function() {
 201  *     return this.newProperty;
 202  *   }
 203  *   
 204  * });
 205  * ~~
 206  * 
 207  * @function
 208  * @param {Object} [target]  Objeto alvo para onde as propriedades serão
 209  *                           copiadas.
 210  * @param {Object}  source   Objeto fonte de onde as propriedades serão
 211  *                           copiadas.
 212  * @return {Object} Retorna o objeto "target" extendido.
 213  * @extends core
 214  * @see jProton.namespace
 215  */
 216 jProton.extend = function() {
 217   var target = this, t = target, source, p, o,
 218       a0 = arguments[0], ai = 0, al = arguments.length;
 219 
 220   // processa o target
 221   if (al > 1) {
 222     ai++;
 223     target = t = a0;
 224   }
 225 
 226   // processa a extensão para cada objeto fonte
 227   for(; source = arguments[ai]; ai++)
 228 
 229     // para cada propriedade do objeto fonte
 230     for(var prop in source) {
 231       p = source[prop];
 232       
 233       // herda as propriedades do objeto fonte
 234       if (prop.charAt(0) != '@') {
 235         
 236         // se a propriedade for um array, extende esse array. Ou seja, se
 237         // já existir algum array na propriedade do objeto destino, concatena 
 238         // com o outro array. Se não existir, copia o array.
 239         if (p && p.splice) {
 240           var tp = t[prop];
 241           t[prop] = tp && tp.splice ? tp.concat(p) : new Array().concat(p);
 242 
 243         // se a propriedade for um objeto, extende esse objeto. Ou seja, se
 244         // já existir algum objeto na propriedade do objeto destino, extende o
 245         // objeto. Se não existir, cria uma cópia do objeto.
 246         } else if (p && typeof p == 'object') {
 247           t[prop] = jProton.extend(t[prop] || {}, p);
 248 
 249         // se for uma propriedade comum, copia seu valor
 250         } else {
 251           t[prop] = p;
 252         }
 253         
 254       } else {
 255         // processa a dependência de módulos
 256         if (prop == '@init') {
 257           p.call(t);
 258           
 259         // processa a dependência de módulos
 260         } else if (prop == '@require') {
 261           for (var ext in p) {
 262 
 263             // versão requerida
 264             var v = p[ext];
 265             
 266             // verifica se extensão requerida está instalada
 267             o = t.extensions[ext] || null;
 268 
 269             // confirma a existência e versão da extensão
 270             if (!o)
 271               throw 'A extensão "'+ext+'" deve estar instalada.';
 272 
 273             else if (o < v && v != 'all')
 274               throw 'A extensão "'+ext+'" deve ter a versão '+v+' ou superior.';
 275           }
 276 
 277         // processa o registro da extensão
 278         } else if (prop == '@extension') {
 279 
 280           // registra a extensão no namespace "extensions" do objeto
 281           o = t.extensions || (t.extensions = {});
 282           for (var name in p) {
 283             o[name] = p[name];
 284           }
 285         }
 286       }
 287     }
 288   // retorna o objeto alvo extendido
 289   return target;
 290 };
 291 
 292 
 293 // Extensão central de jProton.
 294 /**#@+ @extends core */
 295 jProton.extend(/** @lends jProton */ {
 296 
 297   '@extension': {'core': '0.3.0a'},
 298 
 299   /**
 300    * Atalho para a função "document.getElementById()".
 301    *  
 302    * @param {String} id
 303    * @return {Element}
 304    */
 305   id: function(id) {
 306     return document.getElementById(id);
 307   },
 308 
 309   /**
 310    * Executa uma função para cada elemento de um array.
 311    * 
 312    * ~~
 313    * // Exibe os elementos de um array
 314    * $.each(array, function(i,e) {
 315    *   alert('O elemento de número ' + i + ' é igual a ' + e);
 316    * });
 317    * ~~
 318    * 
 319    * @param {Array}    a   Array a ser percorrido.
 320    * @param {Function} fn  Função a ser chamada para cada elemento.
 321    */
 322   each: function(a, fn) {
 323     for(var i=0, ai; ai=a[i]; i++)
 324       fn.call(ai, i, ai);
 325   },
 326 
 327   /**
 328    * Remove os espaços laterais de uma string.
 329    * 
 330    * @param {String}  s  String a ser alterada.
 331    * @return {String}
 332    */
 333   trim: function(s) {
 334     return s.replace(/^\s*|\s*$/g, '');
 335   },
 336 
 337   /** 
 338    * Função vazia usada para remover funções adicionadas a elementos.
 339    */
 340   emptyFn: function() {}
 341 
 342   /**#@-*/
 343 });
 344 
 345 
 346 /**
 347  * Principal classe do framework, que permite a seleção e manipulação 
 348  * simultânea de conjuntos de elementos. Na prática, você raramente irá 
 349  * instanciar manualmente uma classe "jProton.Set". Ao invés disso, é 
 350  * mais conveniente usar a função "jProton()", ou o atalho "$()", pois os dois 
 351  * códigos abaixo:
 352  * 
 353  * ~~
 354  * // Usa o namespace jProton para instanciar a classe jProton.Set
 355  * jProton(selector, context)
 356  * // Usa o namespace alternativo $ para instanciar a classe jProton.Set
 357  * $(selector, context)
 358  * ~~
 359  * 
 360  * equivalem a:
 361  *    
 362  * ~~
 363  * // Instancia explicitamente um novo objeto da classe jProton.Set 
 364  * new jProton.Set().select(selector, context)
 365  * ~~
 366  * @extends core
 367  * @class Principal classe do framework, que permite a seleção e manipulação 
 368  * simultânea de conjuntos de elementos.
 369  */
 370 jProton.Set = function() {};
 371 
 372 // A classe jProton.Set é uma sublcasse de Array
 373 jProton.Set.prototype = new Array();
 374 
 375 /**
 376  * Atalho para incluir funcionalidades na classe jProton.Set.
 377  * 
 378  * @type {jProton.Set}
 379  * @extends core
 380  */
 381 jProton.set = jProton.Set.prototype;
 382 
 383 // Atalho para jProton.set
 384 var set = jProton.set;
 385 
 386 // Adiciona a função extend para a classe jProton.Set
 387 set.extend = jProton.extend;
 388 
 389 
 390 // Extensão central da classe jProton.Set.
 391 /**#@+ @extends core */
 392 set.extend(/** @lends jProton.Set.prototype */ {
 393 
 394   '@extension': {'core': '0.3.0a'},
 395 
 396   /** 
 397    * Referência para o último conjunto da cadeia de operações.
 398    * 
 399    * @type jProton.Set
 400    */
 401   _lastSet: null,
 402 
 403   /** 
 404    * Versão do framework.
 405    * 
 406    * @type String
 407    */
 408   jproton: 'jProton.0.3.9a',
 409 
 410   /**
 411    * Método privado usado para ligar diferentes operações em cadeia. Será 
 412    * instanciado um novo objeto da classe "jProton.Set", vazio, ligado ao 
 413    * objeto atual pela referência do parâmetro "jProton.Set._lastSet". Caso 
 414    * seja informado algum array de elementos, o novo objeto será preenchido 
 415    * com esse conjunto de elementos.
 416    * 
 417    * @param {Array} [e] Array de elementos
 418    * @return {jProton.Set}
 419    */
 420   _chain: function(e) {
 421     var r = new jProton().copy(e);
 422 
 423     r._lastSet = this;
 424 
 425     return r;
 426   },
 427 
 428   /**
 429    * Adiciona os elementos que correspondem ao seletor informado. O parâmetro
 430    * seletor indica quais elementos serão selecionados, enquanto que o 
 431    * parâmetro contexto indica nos descendentes de qual elemento será será
 432    * feita a busca. Se nenhum contexto for informado, ele será considerado o
 433    * "document", ou seja, a busca ocorrerá em todo o documento. Opcionalmente,
 434    * pode-se passar um seletor como contexto, e nesse caso, o primeiro elemento
 435    * selecionado será usado como contexto.
 436    * 
 437    * @param {String}  selector  Seletor que descreve os elementos a serem 
 438    *                            escolhidos.
 439    * @param {Element} [context] Contexto usado na busca. O padrão é "document".
 440    * @return {jProton.Set}
 441    */
 442   select: function(selector, context) {
 443     var type = typeof selector;
 444 
 445     // processa $(expr)
 446     if (type == 'string') {
 447       return this.copy(query.select(selector, context));
 448 
 449     // processa $(obj)
 450     } else if (type == 'object') {
 451 
 452       // processa $(element)
 453       if (selector.nodeName) {
 454         this.push(selector);
 455 
 456       // processa $(array-like)
 457       } else if (selector.length) {
 458         return this.copy(selector);
 459       }
 460     }
 461 
 462     return this; 
 463   },
 464   
 465   /**
 466    * Adiciona novos elementos ao conjunto.
 467    * 
 468    * @param {String}  selector   Seletor que descreve os elementos a serem 
 469    *                             adicionados.
 470    * @param {Element} [context]  Contexto usado na busca. O padrão é "document".
 471    * @return {jProton.Set}
 472    */
 473   add: function(selector, context) {
 474     return this._chain(this).select(selector, context);
 475   },
 476 
 477   /**
 478    * Procura por elementos dentro dos elementos selecionados. O conjunto atual
 479    * de elementos selecionados será usado como contexto de uma nova busca.
 480    * 
 481    * @param {String}  selector   Seletor que descreve os elementos a serem 
 482    *                             pesquisados.
 483    * @return {jProton.Set}
 484    */
 485   find: function(selector) {
 486     return this._chain().select(selector, this);
 487   },
 488 
 489   /**
 490    * Filtra os elementos selecionados deixando apenas os que satisfaçam ao 
 491    * seletor.
 492    * 
 493    * @param {String}  selector   Seletor que descreve os elementos a serem 
 494    *                             filtrados.
 495    * @return {jProton.Set}
 496    */
 497   filter: function(selector) {
 498     return this._chain().copy(query.filter(this, selector));
 499   },
 500   
 501   /**
 502    * Filtra os elementos selecionados removendo aqueles que satisfaçam ao 
 503    * seletor.
 504    * 
 505    * @param {String}  selector   Seletor que descreve os elementos a serem 
 506    *                             filtrados.
 507    * @return {jProton.Set}
 508    */
 509   not: function(selector) {
 510     return this._chain().copy(query.filter(this, selector, true));
 511   },
 512   
 513   /**
 514    * Procura pelo próximo irmão de cada elemento selecionado que satisfaça ao 
 515    * seletor.
 516    * 
 517    * @param {String}  selector   Seletor que descreve os elementos a serem 
 518    *                             encontrados.
 519    */
 520   next: function(selector){
 521     for(var i=0, l=this.length; i<l; i++)
 522       while((this[i] = this[i].nextSibling) && this[i].nodeType != 1);
 523 
 524     return selector ? this.filter(selector) : this;
 525   },
 526 
 527   /**
 528    * Procura pelo irmão anterior de cada elemento selecionado que satisfaça ao 
 529    * seletor.
 530    * 
 531    * @param {String}  selector   Seletor que descreve os elementos a serem 
 532    *                             encontrados.
 533    */
 534   prev: function(selector){
 535     for(var i=0, l=this.length; i<l; i++)
 536       while((this[i] = this[i].previousSibling) && this[i].nodeType != 1);
 537 
 538     return selector ? this.filter(selector) : this;
 539   },
 540 
 541   /**
 542    * Encerra a operação atual e retorna o último objeto "jProton.Set" utilizado
 543    * na cadeia.
 544    * 
 545    * @return {jProton.Set}
 546    */
 547   end: function() {
 548     return this._lastSet || new jProton.Set();
 549   },
 550 
 551   /**
 552    * Executa uma função para cada elemento selecionado.
 553    * 
 554    * ~~
 555    * // Exibe o conteúdo de cada elemento H1 existente no documento.
 556    * $('h1').each(function(i){
 557    *   alert(this.innerHTML);
 558    * });
 559    * ~~
 560    *    
 561    * @param {Function} fn  Função a ser executada para cada elemento 
 562    *                       selecionado. Essa função é chamada passando como
 563    *                       parâmetro o índice do elemento. O elemento por sua
 564    *                       vez é acessado pela palavra-chave "this".
 565    * @return {jProton.Set}
 566    */
 567   each: function(fn) {
 568     for(var i = 0, ei; ei = this[i]; i++)
 569       fn.call(ei, i);
 570 
 571     return this;
 572   },
 573 
 574   /**
 575    * Copia todos elementos de um array.
 576    * 
 577    * @param {Array}  a  Array a ser copiado.
 578    * @return {jProton.Set}
 579    */
 580   copy: function(a) {
 581     if (a) {
 582       if (a.splice) {
 583         this.push.apply(this, a);
 584 
 585       } else {
 586         for(var i = 0, ai; ai = a[i]; i++) {
 587           this.push(ai);
 588         }
 589       }
 590     }
 591     return this;
 592   }
 593 
 594   /**#@-*/
 595 });
 596 
 597 
 598 /**
 599  * Namespace responsável pela manipulação de elementos DOM.
 600  * 
 601  * @name jProton.element
 602  * @namespace
 603  */
 604 jProton.namespace('jProton.element');
 605 
 606 // Atalho para jProton.element
 607 var element = jProton.element;
 608 
 609 
 610 // Extensão dom para jProton.element.
 611 /**#@+ @extends dom */
 612 jProton.extend(element, /** @lends jProton.element */ {
 613   '@extension': {'dom': '0.3.0a'},
 614   
 615   /**
 616    * Retorna o valor da propriedade do elemento.
 617    *      
 618    * @name attr
 619    * @param  {Element}  e     Elemento alvo.         
 620    * @param  {String}   key   Nome da propiedade.
 621    * @return {Value}
 622    */
 623      
 624   /**
 625    * Altera o valor da proriedade do elemento.
 626    * 
 627    * @param  {Element}  e     Elemento alvo.         
 628    * @param  {String}   key   Nome da propiedade.
 629    * @param  {Value}    val   Valor a ser definido.
 630    */
 631   attr: function(e, key, val) {
 632     return e ? val ? e[key] = val : e[key] : undefined;
 633   },
 634   
 635   /**
 636    * Retorna o valor da propriedade 'value' do elemento.
 637    *    
 638    * @name val
 639    * @memberOf jProton.element;
 640    * @param  {Element}  e     Elemento alvo.         
 641    * @return {Value}
 642    */
 643    
 644   /**
 645    * Altera valor da propriedade "value" do elemento. Se o elemento em questão 
 646    * for do tipo "select options", a opção com o mesmo valor será selecionada.  
 647    *    
 648    * @name val
 649    * @memberOf jProton.element;
 650    * @param {Element} e    elemento alvo.         
 651    * @param {String}  val  valor a ser atrubuído a propriedade "value".
 652    */
 653            
 654   /**
 655    * Marca ou seleciona elementos do tipo "select options", "checkbox" ou 
 656    * "radio button".
 657    * 
 658    * ~~
 659    * // Seleciona as opções 'Multiple2' e 'Multiple3' do select de id 'multiple'   
 660    * $('#multiple').val(['Multiple2', 'Multiple3']);
 661    *    
 662    * // Marca o checkbox de valor 'check2' e o radio button de valor 'radio1'
 663    * $('input').val(['check2', 'radio1']);
 664    * ~~
 665    * 
 666    * @param {Element} e        Elemento alvo.         
 667    * @param {Array}   values   Array de Strings com os valores dos elementos
 668    *                           que serão marcados ou selecionados.
 669    *                        
 670    * @return {jProton.query}
 671    */
 672   val: function(e, val) {
 673     if (e) {
 674       // processa $().val(val)
 675       if (val) {
 676         var valType = typeof val;
 677   
 678         // processa $().val(String)
 679         if (valType == 'string')
 680           e.value = val;
 681   
 682         // processa $().val(Array)
 683         else if (valType == 'object') {
 684           var vl = val.length, tag, type;
 685   
 686           // seleciona um ou mais elementos 'checkbox' ou 'radio'
 687           if ((tag = e.nodeName.toLowerCase()) == 'input' && 
 688               ((type = e.type) == 'checkbox' || type == 'radio')) {
 689             e.checked = false;
 690             for (var j=0; j < vl; j++)
 691               if (e.value == val[j])
 692                 e.checked = true;
 693   
 694           // seleciona uma ou mais opções do elemento 'select'
 695           } else if (tag == 'select') {
 696             for (var o=0, op, op=e.options, ol=o.length; o<ol; o++) {
 697               if (e.multiple) 
 698                 op[o].selected = false;
 699   
 700               for (var j=0; j < vl; j++)
 701                 if (op[o].value == val[j])
 702                   op[o].selected = true;
 703             }
 704           }
 705         }
 706       // processa $().val()
 707       } else {
 708         // se for um elemento comum, retorna seu valor
 709         if (e.nodeName.toLowerCase() != 'select')
 710           return e.value;
 711   
 712         // se for um elemento 'select' retorna as opções selecionadas
 713         else {
 714           var r = new Array();
 715           for (var i=0, o=e.options, ol=o.length; i<ol; i++)
 716             if (o[i].selected)
 717               r.push(o[i].value);
 718   
 719           return e.multiple ? r : r[0];
 720         }
 721       }
 722     } else
 723       return undefined;
 724   },
 725   
 726   /**
 727    * Retorna o conteúdo de texto do elemento.
 728    *    
 729    * @name text
 730    * @param  {Element} e   Elemento alvo.         
 731    * @return {String}
 732    */
 733 
 734   /**
 735    * Aletar o conteúdo de texto do elemento.
 736    * 
 737    * @name text
 738    * @param {Element} e    Elemento alvo.         
 739    * @param {String}  val  Conteúdo de texto a ser atribuído.
 740    * @return {jProton.query}
 741    */
 742   text: (function() {
 743     var txt = typeof document.textContent != 'undefined' ?
 744         'textContent' : 'innerText';
 745 
 746     var text = function(e, val) {
 747       return e ? val ? e[txt] = val : e[txt] : undefined;
 748     };
 749 
 750     return text;
 751   })()
 752 
 753   /**#@-*/
 754 });
 755 
 756 
 757 // Extensão dom para jProton.Set.
 758 /**#@+ @extends dom */
 759 set.extend(/** @lends jProton.Set.prototype */ {
 760 
 761   '@extension': {'dom': '0.3.0a'},
 762 
 763   /**
 764    * Retorna o valor da propriedade do primeiro elemento selecionado. Se a 
 765    * propriedade não existir, retorna undefined.   
 766    * 
 767    * @param  {String}   key   Nome da propiedade.
 768    * @return {Value}
 769    */
 770 
 771   /**
 772    * Altera o valor da proriedade de todos os elementos selecionados.
 773    * 
 774    * @param  {String}   key   Nome da propiedade.
 775    * @param  {Value}    val   Valor a ser definido.
 776    * @return {jProton.Set}
 777    */
 778   attr: function(key, val) {
 779     if (val) {
 780       // Processa $().attr(key, val)
 781       for(var i = 0, ei; ei = this[i]; i++)
 782         element.attr(ei, key, val);
 783 
 784       return this;
 785     } else
 786       // Processa $().attr(key)
 787       return element.attr(this[0], key);
 788   },
 789 
 790   /**
 791    * Retorna o valor da propriedade 'value' do primeiro elemento selecionado.
 792    * 
 793    * @return {Value}
 794    */
 795 
 796   /**
 797    * Altera valor à propriedade "value" de todos elementos selecionados. Se
 798    * o elemento em questão for do tipo "select options", a opção com o mesmo
 799    * valor será selecionada.  
 800    * 
 801    * ~~
 802    * // Seleciona a opção que possui valor 'op1' de todos elementos 'select'   
 803    * $('select').val('op1');
 804    * ~~
 805    * 
 806    * @param {String}  val  Valor a ser atrubuído a propriedade "value".
 807    * @return {jProton.Set}
 808    */
 809 
 810   /**
 811    * Marca ou seleciona elementos do tipo "select options", "checkbox" ou 
 812    * "radio button".
 813    * 
 814    * ~~
 815    * // Seleciona as opções 'Multiple2' e 'Multiple3' do select de id 'multiple'   
 816    * $('#multiple').val(['Multiple2', 'Multiple3']);
 817    *    
 818    * // Marca o checkbox de valor 'check2' e o radio button de valor 'radio1'
 819    * $('input').val(['check2', 'radio1']);
 820    * ~~
 821    *
 822    * @param {Array}   values   Array de Strings com os valores dos elementos
 823    *                           que serão marcados ou selecionados.
 824    *                        
 825    * @return {jProton.Set}
 826    */
 827   val: function(val) {
 828     if (val) {
 829       // Processa $().val(val)
 830       for(var i = 0, ei; ei = this[i]; i++)
 831         element.val(ei, val);
 832 
 833       return this;
 834     } else
 835       // Processa $().val()
 836       return element.val(this[0]);
 837   },
 838 
 839   /**
 840    * Retorna o conteúdo HTML do primeiro elemento selecionado.
 841    * 
 842    * @return {String}
 843    */
 844 
 845   /**
 846    * Aletar o conteúdo HTML de todos elementos selecionados.
 847    * 
 848    * @param {String}  val   Conteúdo HTML a ser atribuído.
 849    * @return {jProton.Set}
 850    */
 851   html: function(val) {
 852     if (val) {
 853       // Processa $().html(val)
 854       for(var i = 0, ei; ei = this[i]; i++)
 855         ei.innerHTML = val;
 856 
 857       return this;
 858     } else
 859       // Processa $().html()
 860       return this[0] ? this[0].innerHTML : undefined;
 861   },
 862 
 863   /**
 864    * Adiciona o conteúdo HTML no final do interior de todos elementos 
 865    * selecionados.
 866    * 
 867    * @param {String}  val   Conteúdo HTML a ser adicionado.
 868    * @return {jProton.Set}
 869    */
 870   append: function(val) {
 871     for(var i = 0, ei; ei = this[i]; i++)
 872       ei.innerHTML += val;
 873 
 874     return this;
 875   },
 876 
 877   /**
 878    * Adiciona o conteúdo HTML no início do interior de todos elementos 
 879    * selecionados.
 880    * 
 881    * @param {String}  val   Conteúdo HTML a ser adicionado.
 882    * @return {jProton.Set}
 883    */
 884   prepend: function(val) {
 885     for(var i = 0, ei; ei = this[i]; i++)
 886       ei.innerHTML = val + ei.innerHTML;
 887 
 888     return this;
 889   },
 890 
 891   /**
 892    * Retorna o conteúdo de texto do primeiro elemento selecionado.
 893    * 
 894    * @return {String}
 895    */
 896 
 897   /**
 898    * Altera o conteúdo de texto de todos os elementos selecionados.
 899    *
 900    * @param {String}  val  Conteúdo de texto a ser atribuído.
 901    * @return {jProton.Set}
 902    */
 903   text: function(val) {
 904     if (val) {
 905       // Processa $().text(val)
 906       for(var i = 0, ei; ei = this[i]; i++)
 907         element.text(ei, val);
 908 
 909       return this;
 910     } else
 911       // Processa $().text()
 912       return element.text(this[0]);
 913   }
 914 
 915   /**#@-*/
 916 });
 917 
 918 
 919 // Extensão css para jProton.
 920 /**#@+ @extends css */
 921 jProton.extend(element, /** @lends jProton.element */ {
 922 
 923   '@extension': {'css': '0.3.0a'},
 924 
 925   /**
 926    * Verifica se o elemento possui uma determinada classe.
 927    * 
 928    * @param {Element}  e      Elemento alvo.         
 929    * @param {String}   name   Nome da classe.
 930    */
 931   hasClass: function(e, name) {
 932     return (' '+e.className+' ').indexOf(' '+name+' ') != -1;
 933   },
 934 
 935   /**
 936    * Processa a lógica de addClass() para um único elemento.
 937    *
 938    * @param {Element}  e      Elemento alvo.         
 939    * @param {String}   name   Nome da classe.
 940    */
 941   addClass: function(e, name) {
 942     // cópia de performance de jProton.hasClass(e, name)
 943     if ((' '+e.className+' ').indexOf(' '+name+' ') == -1)
 944       e.className = e.className ? e.className + ' ' + name : name; 
 945   },
 946 
 947   /**
 948    * Processa a lógica de removeClass() para um único elemento.
 949    * 
 950    * @param {Element}  e      Elemento alvo.         
 951    * @param {String}   name   Nome da classe.
 952    */
 953   removeClass: function(e, name) {
 954     e.className = (' ' + e.className + ' ').
 955         replace(new RegExp('(\\S*)\\s+'+name+'\\s+(\\S*)', 'g'), '$1 $2').
 956         replace(/^\s*|\s*$/g, '');
 957   },
 958 
 959   /**
 960    * Alterna o uso de uma classe em todos os elementos selecionados.
 961    *
 962    * @param {Element} e      Elemento alvo.         
 963    * @param {String}  name   Nome da classe.
 964    */
 965   toggleClass: function(e, name) {
 966     // cópia de performance de jProton.hasClass(e, name)
 967     if ((' '+e.className+' ').indexOf(' '+name+' ') >= 0)
 968       this.removeClass(e, name)
 969     else
 970       this.addClass(e, name);
 971   },
 972 
 973   /**
 974    * Retorna o valor da propriedade de estilo do elemento.
 975    * Baseado em: [[http://www.quirksmode.org/dom/getstyles.html|quirksmode]].
 976    * 
 977    * @param {Element} e      Elemento alvo.         
 978    * @param {String}  name   Nome da propriedade de estilo.
 979    * @param {String}  val    Valor a ser atribuído.
 980    */
 981   css: function(e, name, val) {
 982     if (e) {
 983       if (val) 
 984         // processa css(name, val)
 985         e.style[name] = val;
 986 
 987       else {
 988         var type = typeof name;
 989 
 990         if (type == 'object')
 991           // processa css(e, {name1: val1, name2: val2})
 992           for (p in name)
 993             e.style[p] = name[p]
 994 
 995         else
 996           // processa css(e, name)
 997           return window.getComputedStyle ? // Tenta o modo Mozilla
 998               document.defaultView.getComputedStyle(e,null)[name] || 
 999               e.style[name] :          // Ou então, tenta a propriedade style
1000               e.currentStyle ?         // Tenta o modo IE
1001               e.currentStyle[name] ||  // Se não der certo,
1002               e.style[name] :          // tenta a propriedade style. Senão,
1003               undefined;               // Não foi possível recuperar o estilo
1004       }
1005     } else
1006       return undefined;
1007   }
1008 
1009   /**#@-*/
1010 });
1011 
1012 
1013 // Extensão css para jProton.Set.
1014 /**#@+ @extends css */
1015 set.extend(/** @lends jProton.Set.prototype */ {
1016 
1017   '@extension': {'css': '0.3.0a'},
1018 
1019   /**
1020    * Verifica se o primeiro elemento selecionado possui uma determinada classe.
1021    *
1022    * @param {String}  name   Nome da classe.
1023    * @return {Boolean}
1024    */
1025   hasClass: function(name) {
1026     return this[0] ? 
1027       // cópia de performance de jProton.hasClass(e, name)
1028       (' '+this[0].className+' ').indexOf(' '+name+' ') != -1 : 
1029       undefined;
1030   },
1031 
1032   /**
1033    * Adiciona a classe a todos elementos selecionados.
1034    * 
1035    * @param {String}  name   Nome da classe.
1036    * @return {jProton.Set}
1037    */
1038   addClass: function(name) {
1039     for(var i = 0, ei; ei = this[i]; i++)
1040       element.addClass(ei, name);
1041 
1042     return this;
1043   },
1044 
1045   /**
1046    * Remove a classe de todos os elementos selecionados.
1047    * 
1048    * @param {String}  name   Nome da classe.
1049    * @return {jProton.Set}
1050    */
1051   removeClass: function(name) {
1052     for(var i = 0, ei; ei = this[i]; i++)
1053       element.removeClass(ei, name);
1054 
1055     return this;
1056   },
1057 
1058   /**
1059    * Alterna o uso de uma classe em todos os elementos selecionados.
1060    * 
1061    * @param {String}  name   Nome da classe.
1062    * @return {jProton.Set}
1063    */
1064   toggleClass: function(name) {
1065     for(var i = 0, ei; ei = this[i]; i++)
1066       element.toggleClass(ei, name);
1067 
1068     return this;
1069   },
1070 
1071   /**
1072    * Retorna o valor da propriedade de estilo do primeiro elemento selecionado.
1073    * 
1074    * @param {String}  name   Nome da propriedade de estilo.
1075    * @return {Value}   
1076    */
1077 
1078   /**
1079    * Altera os valores de um conjunto de propriedades de todos os elementos 
1080    * selecionados.
1081    * 
1082    * @param {Object}  properties   Objeto contendo pares de propriedade/valor.
1083    * @return {jProton.Set}
1084    */
1085 
1086   /**
1087    * Altera o valor da propriedade de estilo de todos os elementos selecionados.
1088    * Baseado em: [[http://www.quirksmode.org/dom/getstyles.html|Quirksmode]].
1089    * 
1090    * @param {String}  name   Nome da propriedade de estilo.
1091    * @param {String}  val    Valor da propriedade.
1092    * @return {jProton.Set}
1093    */
1094   css: function(name, val) {
1095     if (val) {
1096       // Processa $().css(name, val)
1097       for(var i = 0, ei; ei = this[i]; i++)
1098         element.css(ei, name, val);
1099 
1100       return this;
1101     } else
1102       // Processa $().css(name)
1103       return element.css(this[0], name);
1104   }
1105 
1106   /**#@-*/
1107 });
1108 
1109 
1110 /**
1111  * Namespace responsável pela manipulação de eventos. Adaptado a partir de: 
1112  * [[http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html|Quirksmode]].
1113  *  
1114  * @name jProton.event
1115  * @namespace
1116  */
1117 /**#@+ @extends event */
1118 jProton.event = function(){
1119   
1120   /**
1121    * Lista de eventos registrados
1122    * @private
1123    * @memberOf jProton.event
1124    * @type Object[]
1125    */
1126   var _events = new Array();
1127   var addEventListener = typeof document.addEventListener != 'undefined';
1128   var attachEvent = typeof document.attachEvent != 'undefined';
1129   
1130   return /** @lends jProton.event */ {
1131     version: 'jProton.event.0.3.9a',
1132   
1133     /**
1134      * Adiciona o tratamento de um evento a um elemento.
1135      * 
1136      * @param {Element}  e     Elemento alvo.
1137      * @param {String}   type  Tipo de evento a ser adicionado.
1138      * @param {Function} fn    Função de tratamento do evento.   
1139      */
1140     add: function(e, type, fn){
1141       _events.push({e: e, type: type, fn: fn});
1142   
1143       if (addEventListener)
1144         e.addEventListener(type, fn, false)
1145 
1146       else if (attachEvent) {
1147         e['e'+type+fn] = fn;
1148         e[type+fn] = function() { e['e'+type+fn](window.event); }
1149         e.attachEvent('on'+type, e[type+fn]);
1150       }
1151     },
1152   
1153     /**
1154      * Remove o tratamento de um evento de um elemento.
1155      * 
1156      * @param {Element}  e     Elemento alvo.
1157      * @param {String}   type  Tipo de evento a ser removido.
1158      * @param {Function} fn    Função de tratamento do evento.   
1159      */
1160     remove: function(e, type, fn){
1161       var l, fs = fn.toString();
1162 
1163       // Remove o evento da lista de eventos
1164       for (var i=0,li; li=_events[i]; i++)
1165         if (li.e==e && li.type==type && (li.fn==fn || li.fn.toString()==fs) ) {
1166           l = _events.splice(i,1)[0];
1167           break;
1168         }
1169 
1170       if (l) {
1171         // tenha certeza que esta apontado para a função original
1172         fn = l.fn;
1173         if (addEventListener)
1174           e.removeEventListener(type, fn, false)
1175 
1176         else if (attachEvent) {
1177           e.detachEvent('on'+type, e[type+fn]);
1178           e[type+fn] = null;
1179           e['e'+type+fn] = null;
1180         }
1181       }
1182     },
1183   
1184     /**
1185      * Remove todos os eventos adicionados.
1186      */     
1187     removeAll: function() {
1188       for (var i=0; li=_events[i]; i++)
1189         this.remove(li.e, li.type, li.fn);
1190     }
1191   }
1192 
1193   /**#@-*/
1194 }();
1195 
1196 
1197 // Extensão event para jProton.Set.
1198 /**#@+ @extends event */
1199 set.extend(/** @lends jProton.Set.prototype */ {
1200 
1201   '@extension': {'event': '0.3.0a'},
1202 
1203   /**
1204    * Trata um determinado evento em todos os elementos selecionados.
1205    * 
1206    * @param {String}   type  Tipo de evento a ser tratado.
1207    * @param {Function} fn    Função de tratamento do evento.
1208    * @return {jProton.Set}
1209    */
1210   on: function(type, fn){
1211     return this.each(function(){
1212       jProton.event.add(this, type, fn);
1213     });
1214   },
1215 
1216   /**
1217    * Cancela o tratamento um determinado evento em todos os elementos 
1218    * selecionados.
1219    *
1220    * @param {String}   type  Tipo de evento a ser tratado.
1221    * @param {Function} fn    Função de tratamento do evento.
1222    * @return {jProton.Set}
1223    */
1224   un: function(type, fn){
1225     return this.each(function(){
1226       jProton.event.remove(this, type, fn);
1227     });
1228   }
1229 
1230   /**#@-*/
1231 });
1232 
1233 
1234 /**
1235  * Namespace responsável pelo controle de recursos AJAX.
1236  * 
1237  * @namespace
1238  */
1239 jProton.ajax = function(options) {
1240   return this.ajax.request(options);
1241 };
1242 
1243 // Atalho para jProton.ajax
1244 var ajax = jProton.ajax;
1245 
1246 jProton.extend(ajax, function() {
1247 
1248   /**#@+
1249    * @memberOf jProton.ajax  
1250    * @extends ajax   
1251    */
1252 
1253   /** 
1254    * Lista de requisições pendentes
1255    * @name _requests
1256    * @type request[]
1257    */
1258   var _requests = new Array();
1259 
1260   /** 
1261    * Objeto "XMLHttpRequest" usado nas requisições.
1262    * @name _transport
1263    * @type XMLHttpRequest
1264    */
1265   var _transport = null;
1266 
1267   /** 
1268    * Função de callback usada para carregar JSON remotamente.
1269    * @name _callback
1270    * @type Function
1271    */
1272   var _callback = null;
1273 
1274   /** 
1275    * Estados da requisição.
1276    * @name _states
1277    * @type String[]
1278    */
1279   var _states = ['Uninitialized','Loading','Loaded','Interactive','Complete'];
1280 
1281   /**#@+ @function */
1282 
1283   /**
1284    * Envia a próxima requisição da fila.
1285    */  
1286   var _sendRequest = function() {
1287     var t = _transport, r = _requests.shift(), data;
1288 
1289     // Abre o objeto XMLHttpRequest
1290     t.open(r.type, r.url, r.async);
1291 
1292     //setRequestHeaders();
1293 
1294     // Registra o objeto para que o servidor saiba que é uma requisição AJAX
1295     t.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
1296 
1297     // Caso tenha sido informado algum dado
1298     if (data = jProton.serialize(r.data))
1299       t.setRequestHeader('Content-Type', r.contentType);
1300 
1301     /** @ignore */
1302     // Tratamento de evento de mudança de estado
1303     t.onreadystatechange = function(){ 
1304         _onStateChange(r); 
1305       }; 
1306 
1307     // Envia a requisição
1308     t.send(data);
1309   };
1310 
1311   /**
1312    * Função de tratamento da mudança de estado da requisição ajax.
1313    */     
1314   var _onStateChange = function(options) {
1315     var fn, o = options, t = _transport;
1316     var state = _getState(t); 
1317 
1318     if (fn = o['on' + state]) fn(_getResponse(o), o);
1319 
1320     if (state == 'Complete') {
1321       var success = t.status == 200, response = _getResponse(o);
1322 
1323       if (fn = o['onUpdate'])
1324         fn(response, o);
1325 
1326       if (fn = o['on' + (success ? 'Success' : 'Failure')])
1327         fn(response, o);
1328 
1329       t.onreadystatechange = jProton.emptyFn;
1330 
1331       if (_requests.length > 0) 
1332         setTimeout(_sendRequest, 10);
1333     }
1334   };
1335 
1336   /**
1337    * Retorna a resposta de acordo com o tipo de dado requisitado.
1338    */  
1339   var _getResponse = function(options) {
1340     var t = _transport, type = options.dataType;
1341 
1342     if      (t.status != 200) return t.statusText
1343     else if (type == 'text')  return t.responseText
1344     else if (type == 'html')  return t.responseText
1345     else if (type == 'xml')   return t.responseXML
1346     else if (type == 'json')  return eval('(' + t.responseText + ')');
1347   };
1348 
1349   /**
1350    * Retorna o atual estado da requisição ajax.
1351    */     
1352   var _getState = function() {
1353     return _states[_transport.readyState];
1354   };
1355 
1356   /**#@-*/
1357   /**#@+ @extends ajax */
1358 
1359   return /** @lends jProton.ajax */ {
1360   
1361     '@extension': {'ajax': '0.3.0a'},
1362   
1363     /**
1364      * Inicializa o módulo ajax, criando o objeto "XMLHttpRequest".
1365      * @ignore
1366      */
1367     '@init': function() {
1368       _transport = null;
1369   
1370       try {
1371         _transport = new XMLHttpRequest();
1372       } catch (e) {
1373         try {
1374           _transport = new ActiveXObject("Msxml2.XMLHTTP");
1375         } catch (e) {
1376           try {
1377             _transport = new ActiveXObject("Microsoft.XMLHTTP");
1378           } catch (e) { }
1379         }
1380       }
1381     },
1382     
1383     /**
1384      * Realiza uma requisição ajax.
1385      * 
1386      * @param {Object}   options               Opções da requisição.  
1387      * @param {String}   options.url           URL a ser requisitada.
1388      * @param {String}   options.type          Tipo de requisição ("get" ou "post"). O padrão é "get".
1389      * @param {Boolean}  options.async         Indica se a requisição é assíncrona. O padrão é "true".   
1390      * @param {String}   options.dataType      Dado requisitado ("text", "html", "xml" ou "json"). O padrão é "text".
1391      * @param {String}   options.contentType   ContentType a ser usado. O padrão é "application/x-www-form-urlencoded".  
1392      * @param {Function} options.onLoading     Função a ser executada antes da requisição ser enviada.
1393      * @param {Function} options.onLoaded      Função a ser executada logo que a requisição for enviada.
1394      * @param {Function} options.onInteractive Função a ser executada durante o recebimento da requisição.
1395      * @param {Function} options.onComplete    Função a ser executada ao completar a requisição.
1396      * @param {Function} options.onUpdate      Função a ser executada após completar a requisição.
1397      * @param {Function} options.onSuccess     Função a ser executada ao completar a requisição com sucesso.
1398      * @param {Function} options.onError       Função a ser executada ao completar a requisição com erro.
1399      */      
1400     request: function(options) {
1401       var o = options || {};
1402   
1403       // Configura as opções que não foram definidas para o seu valor padrão
1404       o.type = o.type && o.type.toLowerCase() || 'get';
1405       o.async = o.async || true;
1406       o.dataType = o.dataType || 'text'; 
1407       o.contentType = o.contentType || 'application/x-www-form-urlencoded';
1408   
1409       _requests.push(o);
1410   
1411       var s = _getState();
1412       if (s == 'Uninitialized' || s == 'Complete') 
1413         _sendRequest();
1414     }  
1415   }
1416 }());
1417 /**#@-*/
1418 
1419 
1420 // Extensão ajax para jProton.Set. Requer extensão dom de jProton.Set.
1421 set.extend({ 
1422 
1423   '@require': {'dom': '0.3'},
1424   '@extension': {'ajax': '0.3.0a'},
1425 
1426   /**#@+
1427    * @function
1428    * @memberOf jProton.Set
1429    * @extends ajax
1430    */
1431 
1432   /**
1433    * Realiza requisição ajax e carrega o conteúdo nos elementos selecionados.
1434    *    
1435    * @param {String}   url       URL a ser requisitada.
1436    * @param {Data}     data      Dados a serem enviados.
1437    * @param {Function} callback  Função de retorno.
1438    * @name load
1439    */
1440   load: function(url, data, callback) {
1441     var d = data || null, fn = callback || null;
1442 
1443     if ((typeof data == 'function') && (typeof callback == 'undefined')) {
1444       d = null;
1445       fn = data;
1446     }
1447 
1448     ajax.request({url: url, data: d, onSuccess: fn,
1449       elements: this, 
1450       onUpdate: function(r,o){
1451         $(o.elements).html(r);
1452       }
1453     });
1454 
1455     return this;
1456   }
1457 
1458   /**#@-*/
1459 });
1460 
1461 
1462 // Extensão ajax para jProton.
1463 jProton.extend({
1464 
1465   '@extension': {'ajax': '0.2.0a'},
1466 
1467   /**#@+
1468    * @function
1469    * @memberOf jProton
1470    * @extends ajax
1471    */
1472 
1473   /**
1474    * Serializa.
1475    * 
1476    * @name serialize
1477    * @param {Object} data Desc
1478    */
1479   serialize: function(data) {
1480   	var r = [''], rl = 0;
1481   	if (data) {
1482   		if (typeof data == 'string')	r[rl++] = data
1483   			
1484   		else if (data.innerHTML && data.elements) {
1485   			for (var i=0,el,l=(el=data.elements).length; i < l; i++)
1486   				if (el[i].name) {
1487   				  r[rl++] = encodeURIComponent(el[i].name); 
1488             r[rl++] = '=';
1489             r[rl++] = encodeURIComponent(el[i].value);
1490             r[rl++] = '&';
1491           }
1492   					
1493   		} else 
1494   			for(param in data) {
1495 				  r[rl++] = encodeURIComponent(param); 
1496           r[rl++] = '=';
1497           r[rl++] = encodeURIComponent(data[param]);
1498           r[rl++] = '&';
1499         }
1500   	}
1501   	return r.join('').replace(/&$/, "");
1502   },
1503 
1504   /**
1505    * Realiza uma requisição ajax do tipo "get", retornando texto.
1506    *    
1507    * @name get
1508    * @param {String}   url       URL a ser requisitada.
1509    * @param {Data}     data      Dados a serem enviados.
1510    * @param {Function} callback  Função de retorno.
1511    */
1512   get: function(url, data, callback) {
1513     var d = data || null, fn = callback || null;
1514 
1515     if ((typeof data == 'function') && (typeof callback == 'undefined')) {
1516       d = null;
1517       fn = data;
1518     }
1519 
1520     ajax.request({url: url, data: d, onSuccess: fn});
1521   },
1522 
1523   /**
1524    * Realiza uma requisição ajax do tipo "get", retornando JSON.
1525    *
1526    * @name getJSON
1527    * @param {String}   url       URL a ser requisitada.
1528    * @param {Data}     data      Dados a serem enviados.
1529    * @param {Function} callback  Função de retorno.
1530    */
1531   getJSON: function(url, data, callback) {
1532     var d = data || null, fn = callback || null;
1533 
1534     if ((typeof data == 'function') && (typeof callback == 'undefined')) {
1535       d = null;
1536       fn = data;
1537     }
1538 
1539     ajax.request({url: url, data: d, dataType: 'json', onSuccess: fn});
1540   },
1541 
1542   /**
1543    * Realiza uma requisição ajax do tipo "get", retornando XML.
1544    *
1545    * @name getXML
1546    * @param {String}   url       URL a ser requisitada.
1547    * @param {Data}     data      Dados a serem enviados.
1548    * @param {Function} callback  Função de retorno.
1549    */
1550   getXML: function(url, data, callback) {
1551     var d = data || null, fn = callback || null;
1552 
1553     if ((typeof data == 'function') && (typeof callback == 'undefined')) {
1554       d = null;
1555       fn = data;
1556     }
1557 
1558     ajax.request({url: url, data: d, dataType: 'xml', onSuccess: fn});
1559   },
1560 
1561   /**
1562    * Realiza uma requisição ajax do tipo "post".
1563    *
1564    * @name post
1565    * @param {String}   url       URL a ser requisitada.
1566    * @param {Data}     data      Dados a serem enviados.
1567    * @param {Function} callback  Função de retorno.
1568    */
1569   post: function(url, data, callback) {
1570     var d = data || null, fn = callback || null;
1571 
1572     if ((typeof data == 'function') && (typeof callback == 'undefined')) {
1573       d = null;
1574       fn = data;
1575     }
1576 
1577     ajax.request({url: url, type: 'post', data: d, onSuccess: fn});
1578   },
1579 
1580   /**
1581    * Carrega um script dinamicamente.
1582    *    
1583    * @name loadScript
1584    * @param {String}   url       URL do script.
1585    */
1586   loadScript: function(url) {
1587     var script = document.getElementById('dynamicScript');
1588 
1589     if (script)
1590       script.parentNode.removeChild(script);
1591 
1592     script = document.createElement('script');
1593     script.setAttribute('src', url);
1594     script.setAttribute('id', 'dynamicScript');
1595     script.setAttribute('type', 'text/javascript');
1596     document.documentElement.firstChild.appendChild(script);
1597   },
1598 
1599   /**
1600    * Carrega JSON remotamente (JSONP).
1601    *    
1602    * @name loadJSONP
1603    * @param {String}   url       URL dos dados.
1604    * @param {String}   jsonp     Nome da função de retorno do servidor. O 
1605    *                             padrão é "callback".
1606    * @param {Function} callback  Função de retorno.
1607    */
1608   loadJSONP: function(url, jsonp, callback) {
1609     var j = jsonp || 'callback', fn = callback || jProton.emptyFn,
1610         script = document.getElementById('dynamicScript');
1611 
1612     if ((typeof jsonp == 'function') && (typeof callback == 'undefined')) {
1613       j = 'callback';
1614       fn = jsonp;
1615     }
1616 
1617     if (script)
1618       script.parentNode.removeChild(script);
1619 
1620     ajax._callback = fn;
1621     script = document.createElement('script');
1622     script.setAttribute('src', url + '&'+ j + '=jProton.ajax._callback');
1623     script.setAttribute('id', 'dynamicScript');
1624     script.setAttribute('type', 'text/javascript');
1625     document.documentElement.firstChild.appendChild(script);
1626   }
1627 
1628   /**#@-*/
1629 });
1630 
1631 
1632 /**
1633  * Namespace responsável pela seleção de elementos através de seletores CSS. 
1634  * Baseado em 
1635  * [[http://extjs.com/deploy/ext/docs/output/Ext.DomQuery.html|DomQuery]].
1636  * 
1637  * @name jProton.query
1638  * @namespace
1639  */
1640 /** @ignore */
1641 jProton.query = function(){
1642   /**#@+ 
1643    * @private 
1644    * @function
1645    * @memberOf jProton.query
1646    * @extends core
1647    */
1648 
1649   var cache = {}, 
1650     simpleCache = {}, 
1651     reTrim = /^\s+|\s+$/g,
1652     reTemplate = /\{(\d+)\}/g,
1653     reMode = /^(\s?[\/>+~]\s?|\s|$)/,
1654     reTag = /^(#)?([\w-\*]+)/,
1655     reNth = /(\d*)n\+?(\d*)/, 
1656     reNth2 = /\D/,
1657 
1658     // This is for IE MSXML which does not support expandos.
1659     // IE runs the same speed using setAttribute, however FF slows way down
1660     // and Safari completely fails so they need to continue to use expandos.
1661     isIE = !!window.ActiveXObject,
1662     key = 30803;
1663 
1664   // this eval is stop the compressor from
1665   // renaming the variable to something shorter
1666   eval("var batch = 30803;");
1667 
1668   function _quickId(e, mode, context, val){
1669     if(e == context){
1670       var d = context.ownerDocument || context;
1671       return d.getElementById(val);
1672     }
1673     e = _getNodes(e, mode, "*");
1674     return _byId(e, val);
1675   };
1676 
1677   var _byId = function(e, val){
1678     if(e.tagName || e == document)
1679       e = [e];
1680 
1681     var r = new Array(), rl = -1;
1682     for(var i = 0, ei; ei = e[i]; i++)
1683       if(ei && ei.id == val){
1684         r[++rl] = ei;
1685         return r;
1686       }
1687     return r;
1688   };
1689 
1690   var _byTag = function(e, val){
1691     if(e.tagName || e == document)
1692       e = [e];
1693 
1694     var r = new Array(), rl = -1;
1695     val = val.toLowerCase();
1696     for(var i = 0, ei; ei = e[i]; i++)
1697       if(ei.nodeType == 1 && ei.tagName.toLowerCase()==val)
1698         r[++rl] = ei;
1699 
1700     return r;
1701   };
1702 
1703   var _byClass = function(e, val){
1704     if(!val)
1705       return e;
1706 
1707     var r = new Array(), rl = -1;
1708     for(var i = 0, ei; ei = e[i]; i++)
1709       if((' '+ei.className+' ').indexOf(val) != -1)
1710         r[++rl] = ei;
1711 
1712     return r;
1713   };
1714 
1715   var _byAttr = function(e, attr, op, val){
1716     var r = new Array(), rl = -1, f = query.operators[op];
1717     for(var i = 0, ei, a; ei = e[i]; i++){
1718       if(attr == "class" || attr == "className")
1719         a = ei.className;
1720       else if(attr == "for")
1721         a = ei.htmlFor;
1722       else if(attr == "href")
1723         a = ei.getAttribute("href", 2)
1724       else
1725         a = ei.getAttribute(attr);
1726 
1727       if((f && f(a, val)) || (!f && a))
1728         r[++rl] = ei;
1729     }
1730     return r;
1731   };
1732 
1733   var _byPseudo = function(e, name, val){
1734     return query.pseudos[name](e, val);
1735   };
1736 
1737   var _getNodes = function(e, mode, name){
1738     var r = new Array(), rl = -1;
1739     if(!e)
1740       return r;
1741 
1742     name = name || "*";
1743     if(typeof e.getElementsByTagName != "undefined")
1744       e = [e];
1745 
1746     if(!mode){
1747       for(var i = 0, ei, n; ei = e[i]; i++){
1748         n = ei.getElementsByTagName(name);
1749         for(var j = 0, nj; nj = n[j]; j++)
1750           r[++rl] = nj;
1751       }
1752     }else if(mode == "/" || mode == ">"){
1753       var utag = name.toUpperCase();
1754       for(var i = 0, ei, n; ei = e[i]; i++){
1755         n = ei.children || ei.childNodes;
1756         for(var j = 0, nj; nj = n[j]; j++)
1757           if(nj.nodeName == utag || nj.nodeName == name  || name == '*')
1758             r[++rl] = nj;
1759 
1760       }
1761     }else if(mode == "+"){
1762       var utag = name.toUpperCase();
1763       for(var i = 0, ei; ei = e[i]; i++){
1764         while((ei = ei.nextSibling) && ei.nodeType != 1);
1765         if(ei && (ei.nodeName == utag || ei.nodeName == name || name == '*'))
1766           r[++rl] = ei;
1767       }
1768     }else if(mode == "~"){
1769       for(var i = 0, ei; ei = e[i]; i++){
1770         while((ei = ei.nextSibling) && (ei.nodeType != 1 || 
1771               (name == '*' || ei.tagName.toLowerCase()!=name)));
1772         if(ei)
1773           r[++rl] = ei;
1774       }
1775     }
1776     return r;
1777   };
1778 
1779   var _unique = function(e){
1780     if(!e)
1781       return new Array();
1782 
1783     var len = e.length, i, r = e, ei;
1784     if(!len || typeof e.nodeType != "undefined" || len == 1)
1785       return e;
1786 
1787     if(isIE && typeof e[0].selectSingleNode != "undefined") {
1788       var d = ++key;
1789       e[0].setAttribute("__unique", d);
1790       var r = [e[0]], rl = 0;
1791       for(var i = 1, ei; ei = e[i]; i++)
1792         if(!ei.getAttribute("__unique") != d){
1793           ei.setAttribute("__unique", d);
1794           r[++rl] = ei;
1795         }
1796   
1797       for(var i = 0; ei = e[i]; i++)
1798         ei.removeAttribute("__unique");
1799   
1800       return r;
1801     }
1802 
1803     var d = ++key;
1804     e[0].__unique = d;
1805     for(i = 1, ei; ei = e[i]; i++){
1806       if(ei.__unique != d)
1807         ei.__unique = d;
1808       else{
1809         r = new Array(), rl = -1;
1810         for(var j = 0; j < i; j++)
1811           r[++rl] = e[j];
1812 
1813         for(j = i+1; ej = e[j]; j++)
1814           if(ej.__unique != d){
1815             ej.__unique = d;
1816             r[++rl] = ej;
1817           }
1818         return r;
1819       }
1820     }
1821     return r;
1822   };
1823 
1824   var _diff = function(e, e2){
1825     if(!e.length)
1826       return e2;
1827 
1828     if(isIE && e[0].selectSingleNode) {
1829       var d = ++key, ei;
1830       for(var i = 0; ei = e[i]; i++)
1831         ei.setAttribute("__diff", d);
1832   
1833       var r = new Array(), rl = -1;
1834       for(var i = 0; ei = e2[i]; i++)
1835         if(ei.getAttribute("__diff") != d)
1836           r[++rl] = ei;
1837   
1838       for(var i = 0; ei = e[i]; i++)
1839         ei.removeAttribute("__diff");
1840   
1841       return r;
1842     }
1843 
1844     var d = ++key;
1845     for(var i = 0; ei = e[i]; i++)
1846       ei.__diff = d;
1847 
1848     var r = new Array(), rl = -1;
1849     for(var i = 0; ei = e2[i]; i++)
1850       if(ei.__diff != d)
1851         r[++rl] = ei;
1852 
1853     return r;
1854   };
1855 
1856   var _next = function(e){
1857     while((e = e.nextSibling) && e.nodeType != 1);
1858     return e;
1859   };
1860 
1861   var _prev = function(e){
1862     while((e = e.previousSibling) && e.nodeType != 1);
1863     return e;
1864   };
1865 
1866   /**#@-*/
1867   /**#@+ @extends core */
1868   return /** @lends jProton.query */ {
1869     /**
1870      * Compiles a selector/xpath query into a reusable function. The returned function
1871      * takes one parameter "context" (optional), which is the context node from where the query should start.
1872      * @param {String} selector The selector/xpath query
1873      * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
1874      * @return {Function}
1875      */
1876     compile: function(selector, type){
1877       type = type || "select";
1878 
1879       var s = selector, ls,
1880         rules = query.rules,
1881         mm, tm, rm, matched, fl = 0, 
1882         f = ["var fn=function(c){\nvar mode; var e=c||document; ++batch;\n"];
1883 
1884       // accept leading mode switch
1885       mm = s.match(reMode);
1886       if(mm && mm[1]){
1887         f[++fl] = 'mode="'+mm[1].replace(reTrim, "")+'";';
1888         s = s.replace(mm[1], "");
1889       }
1890 
1891       // strip leading slashes
1892       while(s.substr(0, 1)=="/")
1893         s = s.substr(1);
1894 
1895       while(s && ls != s){
1896         ls = s;
1897         tm = s.match(reTag);
1898         if(type == "select"){
1899           if(tm){
1900             if(tm[1] == "#")
1901               f[++fl] = 'e = _quickId(e, mode, c, "'+tm[2]+'");';
1902             else
1903               f[++fl] = 'e = _getNodes(e, mode, "'+tm[2]+'");';
1904 
1905             s = s.replace(tm[0], "");
1906           }else if(s.substr(0, 1) != '@')
1907             f[++fl] = 'e = _getNodes(e, mode, "*");';
1908 
1909         }else
1910           if(tm){
1911             if(tm[1] == "#")
1912               f[++fl] = 'e = _byId(e, "'+tm[2]+'");';
1913             else
1914               f[++fl] = 'e = _byTag(e, "'+tm[2]+'");'
1915 
1916             s = s.replace(tm[0], "");
1917           }
1918 
1919         while(!(mm = s.match(reMode))){
1920           matched = false;
1921           for(var j = 0; rm = rules[j]; j++){
1922             var m = s.match(rm.re);
1923             if(m){
1924               f[++fl]=rm.select.replace(reTemplate, function(e,i){return m[i];});
1925               s = s.replace(m[0], "");
1926               matched = true;
1927               break;
1928             }
1929           }
1930           // prevent infinite loop on bad selector
1931           if(!matched)
1932             throw 'Error parsing selector, parsing failed at "' + s + '"';
1933         }
1934         if(mm[1]){
1935           f[++fl] = 'mode="'+mm[1].replace(reTrim, "")+'";';
1936           s = s.replace(mm[1], "");
1937         }
1938       }
1939       f[++fl] = "return _unique(e);\n}";
1940       eval(f.join(""));
1941       return fn;
1942     },
1943 
1944     /**
1945      * Selects a group of elements.
1946      * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
1947      * @param {Node} context (optional) The start of the query (defaults to document).
1948      * @return {Array}
1949      */
1950     select: function(selector, context){
1951       context = context || document;
1952 
1953       if(typeof context == "string")
1954         context = document.getElementById(context);
1955 
1956       var selectors = selector.split(","), len = selectors.length, results = new Array();
1957       for(var i = 0; i < len; i++){
1958         var s = selectors[i].replace(reTrim, "");
1959         if(!cache[s])
1960           if(!(cache[s] = query.compile(s)))
1961             throw s + " is not a valid selector";
1962 
1963         var result = cache[s](context);
1964         if(result && result != document)
1965           results = results.concat(result);
1966       }
1967       if(len > 1)
1968         return _unique(results);
1969 
1970       return results;
1971     },
1972 
1973     /**
1974      * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
1975      * @param {String/HTMLElement/Array} e An element id, elvalent or array of elements
1976      * @param {String} selector The simple selector to test
1977      * @return {Boolean}
1978      */
1979     is: function(e, ss){
1980       if(typeof e == "string")
1981         e = document.getElementById(e);
1982 
1983       var isArray = !!e.splice,
1984           result = query.filter(isArray ? e : [e], ss);
1985       return isArray ? (result.length == e.length) : (result.length > 0);
1986     },
1987 
1988     /**
1989      * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
1990      * @param {Array} e An array of elements to filter
1991      * @param {String} selector The simple selector to test
1992      * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
1993      * the selector instead of the ones that match
1994      * @return {Array}
1995      */
1996     filter: function(e, ss, nonMatches){
1997       ss = ss.replace(reTrim, "");
1998       if(!simpleCache[ss])
1999         simpleCache[ss] = query.compile(ss, "simple");
2000 
2001       var result = simpleCache[ss](e);
2002       return nonMatches ? _diff(result, e) : result;
2003     },
2004 
2005     /**
2006      * Collection of matching regular expressions and code snippets.
2007      */
2008     rules: [{
2009         re: /^\.([\w-]+)/,
2010         select: 'e = _byClass(e, " {1} ");'
2011       }, {
2012         re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
2013         select: 'e = _byPseudo(e, "{1}", "{2}");'
2014       },{
2015         re: /^\[([\w-]+)(?:(.?=)["']?(.+?)["']?)?\]/,
2016         select: 'e = _byAttr(e, "{1}", "{2}", "{3}");'
2017       }, {
2018         re: /^#([\w-]+)/,
2019         select: 'e = _byId(e, "{1}");'
2020       }
2021     ],
2022 
2023     /**
2024      * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
2025      * New operators can be added as long as the match the format <i>c</i>= where <i>c</i> is any character other than space, > <.
2026      */
2027     operators: {
2028       "=": function(attr, val){
2029         return attr == val;
2030       },
2031       "!=": function(attr, val){
2032         return attr != val;
2033       },
2034       "^=": function(attr, val){
2035         return attr && attr.substr(0, val.length) == val;
2036       },
2037       "$=": function(attr, val){
2038         return attr && attr.substr(attr.length-val.length) == val;
2039       },
2040       "*=": function(attr, val){
2041         return attr && attr.indexOf(val) !== -1;
2042       },
2043       "%=": function(attr, val){
2044         return (attr % val) == 0;
2045       },
2046       "|=": function(attr, val){
2047         return attr && (attr == val || attr.substr(0, val.length+1) == val+'-');
2048       },
2049       "~=": function(attr, val){
2050         return attr && (' '+attr+' ').indexOf(' '+val+' ') != -1;
2051       }
2052     },
2053 
2054     /**
2055      * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
2056      * and the argument (if any) supplied in the selector.
2057      */
2058     pseudos: {
2059       "first-child": function(e){
2060         var r = new Array(), rl = -1, n;
2061         for(var i = 0, ei; ei = n = e[i]; i++){
2062           while((n = n.previousSibling) && n.nodeType != 1);
2063           if(!n)
2064             r[++rl] = ei;
2065         }
2066         return r;
2067       },
2068 
2069       "last-child": function(e){
2070         var r = new Array(), rl = -1, n;
2071         for(var i = 0, ei; ei = n = e[i]; i++){
2072           while((n = n.nextSibling) && n.nodeType != 1);
2073           if(!n)
2074             r[++rl] = ei;
2075         }
2076         return r;
2077       },
2078 
2079       "nth-child": function(e, val) {
2080         var r = new Array(), rl = -1, m = reNth.exec(val == "even" && "2n" || 
2081           val == "odd" && "2n+1" || !reNth2.test(val) && "n+" + val || val),
2082           f = (m[1] || 1) - 0, l = m[2] - 0;
2083         for(var i = 0, ei; ei = e[i]; i++){
2084           var p = ei.parentNode;
2085           if (batch != p._batch) {
2086             var j = 0;
2087             for(var n = p.firstChild; n; n = n.nextSibling)
2088               if(n.nodeType == 1)
2089                  n.nodeIndex = ++j;
2090 
2091             p._batch = batch;
2092           }
2093           if (f == 1) {
2094             if (l == 0 || ei.nodeIndex == l)
2095               r[++rl] = ei;
2096 
2097           } else if ((ei.nodeIndex + l) % f == 0)
2098             r[++rl] = ei;
2099         }
2100 
2101         return r;
2102       },
2103 
2104       "only-child": function(e){
2105         var r = new Array(), rl = -1;;
2106         for(var i = 0, ei; ei = e[i]; i++)
2107           if(!_prev(ei) && !_next(ei))
2108             r[++rl] = ei;
2109 
2110         return r;
2111       },
2112 
2113       "empty": function(e){
2114         var r = new Array(), rl = -1;
2115         for(var i = 0, ei; ei = e[i]; i++){
2116           var n = ei.childNodes, j = -1, nj, empty = true;
2117           while(nj = n[++j])
2118             if(nj.nodeType == 1 || nj.nodeType == 3){
2119               empty = false;
2120               break;
2121             }
2122 
2123           if(empty)
2124             r[++rl] = ei;
2125         }
2126         return r;
2127       },
2128 
2129       "contains": function(e, val){
2130         var r = new Array(), rl = -1;
2131         for(var i = 0, ei; ei = e[i]; i++)
2132           if((ei.textContent||ei.innerText||'').indexOf(val) != -1)
2133             r[++rl] = ei;
2134 
2135         return r;
2136       },
2137 
2138       "nodeValue": function(e, val){
2139         var r = new Array(), rl = -1;
2140         for(var i = 0, ei; ei = e[i]; i++)
2141           if(ei.firstChild && ei.firstChild.nodeValue == val)
2142             r[++rl] = ei;
2143 
2144         return r;
2145       },
2146 
2147       "checked": function(e){
2148         var r = new Array(), rl = -1;
2149         for(var i = 0, ei; ei = e[i]; i++)
2150           if(ei.checked == true)
2151             r[++rl] = ei;
2152 
2153         return r;
2154       },
2155 
2156       "not": function(e, val){
2157         return query.filter(e, val, true);
2158       },
2159 
2160       "any": function(e, val){
2161         var r = new Array(), rl = -1, s, ss = val.split('|');
2162         for(var i = 0, ei; ei = e[i]; i++)
2163           for(var j = 0; s = ss[j]; j++)
2164             if(query.is(ei, s)){
2165               r[++rl] = ei;
2166               break;
2167             }
2168 
2169         return r;
2170       },
2171 
2172       "odd": function(e){
2173         return this["nth-child"](e, "odd");
2174       },
2175 
2176       "even": function(e){
2177         return this["nth-child"](e, "even");
2178       },
2179 
2180       "nth": function(e, val){
2181         return e[val-1] || new Array();
2182       },
2183 
2184       "first": function(e){
2185         return e[0] || new Array();
2186       },
2187 
2188       "last": function(e){
2189         return e[e.length-1] || new Array();
2190       },
2191 
2192       "has": function(e, val){
2193         var r = new Array(), rl = -1, s = query.select;
2194         for(var i = 0, ei; ei = e[i]; i++)
2195           if(s(val, ei).length > 0)
2196             r[++rl] = ei;
2197 
2198         return r;
2199       },
2200 
2201       "next": function(e, val){
2202         var r = new Array(), rl = -1, is = query.is;
2203         for(var i = 0, ei; ei = e[i]; i++){
2204           var n = _next(ei);
2205           if(n && is(n, val))
2206             r[++rl] = ei;
2207         }
2208         return r;
2209       },
2210 
2211       "prev": function(e, val){
2212         var r = new Array(), rl = -1, is = query.is;
2213         for(var i = 0, ei; ei = e[i]; i++){
2214           var n = _prev(ei);
2215           if(n && is(n, val))
2216             r[++rl] = ei;
2217         }
2218         return r;
2219       }
2220     }
2221   }
2222 }();
2223 
2224 // Atalho para jProton.query
2225 var query = jProton.query;
2226 
2227 })();