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 })();