<pedrocorreia.net ⁄>
corner
<mySearch ⁄> <mySearch ⁄>

corner
 
corner
<mySnippets order="rand" ⁄> <mySnippets order="rand" ⁄>

corner
 
corner
<myContacts ⁄> <myContacts ⁄>

<email ⁄>


pc@pedrocorreia.net

<windows live messenger ⁄>


pedrojacorreia@hotmail.com

<myCurriculum type="pdf" ⁄>


Download
corner
 
corner
<myBlog show="last" ⁄> <myBlog show="last" ⁄>

corner
 
corner
<myNews show="rand" ⁄> <myNews show="rand" ⁄>

corner
 
corner
<myNews type="cat" ⁄> <myNews type="cat" ⁄>

corner
 
corner
<myQuote order="random" ⁄> <myQuote order="random" ⁄>

corner
 
corner
<myPhoto order="random" ⁄> <myPhoto order="random" ⁄>

<pedrocorreia.net ⁄>
corner
 
corner
<myAdSense ⁄> <myAdSense ⁄>

corner
 
corner
<myVisitorsMap ⁄> <myVisitorsMap ⁄>

corner
 
 

<Actualizar DropDownList utilizando Ajax ⁄ >




clicks: 11840 11840 2007-11-24 2007-11-24 goto mySnippets mySnippets php  Download  Bookmark This Bookmark This



Bem lá vai mais um snippet sobre uma das buzzwords do momento, Ajax. Praticamente o snippet todo será baseado no J de Ajax. Este será composto por várias classes. Para troca de informação com o servidor vou usar JSON (JavaScript Object Notation).
Já tinha falado sobre JSON num snippet anterior, podem dar uma vista de olhos ou então pelo Google acha-se um pouco de tudo ou ainda consultar o site oficial.

Iremos ter uma abordagem OOP no Javascript e recorrer também a Unobtrusive JavaScript, bem com tanta buzzword, espero que isto corra bem!

Basicamente o que este snippet irá exemplificar é uma situação em que temos 2 dropdowns encadeadas, em que a 2ª é baseada na escolha da 1ª, isto é, ao selecionarmos um item na 1ª dropdown, a 2ª vai ser preenchida com informação proveniente do servidor, baseada na opção escolhida. No código server-side não vou alongar-me muito, nem vai ser muito dinâmico, porque tenho as respostas hard-coded, este não era o principal objectivo do snippet e como tal iria só alongar ainda mais o texto. Mas geralmente comunica-se com a BD, vai-se buscar uns valores, etc, etc e devolve-se a resposta pretendida. Os pedidos são respondidos por um script PHP, mas podia ser outra coisa qualquer, desde que respeite o formato json aceite pelo script.


Vamos separar o código (essencialmente javascript) por vários ficheiros, para tentar uma maior aproximação a OOP.

Mas despachemos já o css, nada de especial, apenas mais do mesmo, como sempre:
  1. body{
  2. font-family: Tahoma, Verdana, Arial;font-size: 8pt;
  3. color: #000;background: #fff;
  4. }
  5.  
  6. #div_main{float: left}
  7.  
  8. #div_loading{}
  9.  
  10. h3{font-family: Consolas, Tahoma, Arial;font-size: 10pt;font-weight: bold;}
  11.  
  12. select, textarea, input{
  13. background-color: #FFFFD4;color: #000000;font-size: 8pt;
  14. font-family: Tahoma, Verdana, Arial, sans-serif;
  15. border: 1px solid #004080;
  16. }



-> Events.js - este ficheiro será responsável por adicionar ou remover eventos a elementos/ objectos da página, por ex. load da página, quanto um elemento é actualizado, etc, etc.
  1. /**
  2. * Class Events - possui vários métodos/ propriedades estáticos comuns
  3. */
  4. Events = function(){
  5. }
  6.  
  7. /**
  8. * Adicionar Event
  9. *
  10. * Adaptada do seguinte URL
  11. * http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
  12. *
  13. * @param Object
  14. * @param Object
  15. * @param Object
  16. */
  17. Events.AddEvent = function(obj, type, fn){
  18. if(!obj) return;
  19.  
  20. this.RemoveEvent(obj, type, fn);
  21. if (obj.addEventListener) {
  22. obj.addEventListener(type, fn, false);
  23. }
  24. else {
  25. if (obj.attachEvent) {
  26. obj["e" + type + fn] = fn;
  27. obj[type + fn] = function(){
  28. obj["e" + type + fn](window.event);
  29. }
  30. obj.attachEvent("on" + type, obj[type + fn]);
  31. }
  32. }
  33. }
  34. /**
  35. * Remover Event
  36. *
  37. * Adaptada do seguinte URL
  38. * http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
  39. *
  40. * @param Object
  41. * @param Object
  42. * @param Object
  43. */
  44. Events.RemoveEvent = function(obj, type, fn){
  45. if (obj.removeEventListener) {
  46. try{obj.removeEventListener(type, fn, false);} catch(e){}
  47. }
  48. else{
  49. if (obj.detachEvent) {
  50. obj.detachEvent("on" + type, fn);
  51. obj[type + fn] = null;
  52. obj["e" + type + fn] = null;
  53. }
  54. }
  55. }
  56.  




-> Misc.js - Class estática, possui vários métodos de uso comum, como por ex. a criação do HttpRequest
  1. /**
  2. * Class Misc - possui vários métodos/ propriedades estáticos comuns
  3. */
  4. Misc = function(){
  5. }
  6.  
  7. // ficheiro que vai responder aos pedidos
  8. Misc.ServerFile = "ajax.php";
  9.  
  10. /**
  11. * Hack IE para ultrapassar problema cache pedidos get
  12. *
  13. * @param String
  14. */
  15. Misc.AntiCacheRand = function(aurl){
  16. var rnd = encodeURI(Math.random());
  17. aurl += (aurl.indexOf("?") >= 0) ? "&foo=" + rnd : "?foo=" + rnd;
  18.  
  19. return aurl;
  20. };
  21.  
  22. /**
  23. * Mensagem a mostrar ao utilizador enquanto
  24. * a informação estiver a ser carregada
  25. *
  26. * @param String
  27. */
  28. Misc.MsgLoading = function(div_name){
  29. var div = $(div_name);
  30.  
  31. if (div.style.display != "block") {
  32. var msg_loading = "A carregar informação ...";
  33. var img = new HTMLControl("loading_animation");
  34. div.innerHTML = img.DoImage("loading.gif", msg_loading, 16, 16);
  35. div.style.display = "block";
  36. }
  37. else {
  38. div.style.display = "none";
  39. }
  40. };
  41.  
  42. /**
  43. * Criar request
  44. */
  45. Misc.CreateHttpRequest = function(){
  46. if (window.XMLHttpRequest) { // Mozilla, Safari,...
  47. http_request = new XMLHttpRequest();
  48.  
  49. if (http_request.overrideMimeType) {
  50. http_request.overrideMimeType('text/html');
  51. }
  52. }
  53. else
  54. if (window.ActiveXObject) { // IE
  55. try {
  56. http_request = new ActiveXObject("Msxml2.XMLHTTP");
  57. }
  58. catch (e) {
  59. try {
  60. http_request = new ActiveXObject("Microsoft.XMLHTTP");
  61. }
  62. catch (e) {
  63. }
  64. }
  65. }
  66.  
  67. if (!http_request) {
  68. alert('Giving up :( Cannot create an XMLHTTP instance');
  69. return false;
  70. }
  71.  
  72. return http_request;
  73. };
  74. //fim class Misc



-> HtmlControl.js - Class que permite criar/ actualizar alguns elementos Html, para este snippet apenas adicionei os métodos necessários
  1. /**
  2. * Class responsável pela criação de objectos html
  3. *
  4. * @param String id -> nome do objecto
  5. */
  6. function HTMLControl(id){
  7. this.id = id;
  8.  
  9. /**
  10. * Método Privado
  11. *
  12. * Gerar atributos name e id
  13. *
  14. * @return String
  15. */
  16. var _GenerateID = function(){return " name='" + id + "' id='" + id + "' ";};
  17.  
  18. /**
  19. * Método Privado
  20. *
  21. * Adicionar elemento option à dropdown
  22. *
  23. * @param String
  24. * @param String
  25. *
  26. */
  27. var _DropdownListAddOption = function(value, description){
  28. $(id).options.add(_DropdownListCreateOption(value, description));
  29. }
  30.  
  31. /**
  32. * Criar element option
  33. *
  34. * @param String
  35. * @param String
  36. */
  37. var _DropdownListCreateOption = function(value, description){
  38. var ddlOption = document.createElement("option");
  39. ddlOption.value = value;
  40. ddlOption.text = description;
  41.  
  42. return ddlOption;
  43. }
  44. /**
  45. * Método Privado
  46. *
  47. * Limpar itens da dropdown
  48. */
  49. var _DropdownListClear = function(){$(id).options.length = 0;}
  50.  
  51. /**
  52. * Construir imagem
  53. *
  54. * @param String src
  55. * @param String title
  56. * @param int width
  57. * @param int height
  58. * @return String
  59. */
  60. this.DoImage = function(src, title, width, height){
  61. title = " title='" + title + "' alt='" + title + "' ";
  62. return "<img src='" + src + "' width='" + width + "' height='" + height + "' " + _GenerateID() + title + " />";
  63. };
  64.  
  65. /**
  66. * Construir dropdown list
  67. *
  68. * @param Object
  69. *
  70. */
  71. this.DoDropdownList = function(arrOptions){
  72. var arr = eval(arrOptions);
  73.  
  74. _DropdownListClear();
  75. var ddl = $(this.id);
  76. var i, value, description;
  77. var count = arr.options.length;
  78.  
  79. for (i = 0; i < count; i++) {
  80. value = arr.options[i].value;
  81. description = arr.options[i].description;
  82.  
  83. _DropdownListAddOption(value, description);
  84. }
  85. }
  86. };
  87. //fim class HTMLControl
  88.  
  89. /**
  90. * Obter um elemento
  91. *
  92. * nota: para usar este método a class HtmlControl
  93. * não precisa de estar instanciada
  94. *
  95. * @param String
  96. */
  97. $ = function(element){return document.getElementById(element);};
  98.  








-> Ajax.js - A class responsável para que o processo de actualização seja executado, vai fazer uma chamada ao servidor e vai processar a sua resposta, chamando os métodos necessários para tal. Recebe a resposta no formato json, para que o javascript consiga "perceber" o que é a resposta, vamos recorrer ao eval.
  1. /**
  2. * Class Ajax
  3. */
  4. Ajax = function(){};
  5.  
  6. Ajax.DivLoadingName="div_loading";
  7.  
  8. /**
  9. * Actualizar dropdown
  10. */
  11. Ajax.UpdateDropdownList = function(ddListName,ddSubListName){
  12. Misc.MsgLoading(this.DivLoadingName); //iniciar loading
  13.  
  14. var ddListValue = $(ddListName).value;
  15. var url = Misc.AntiCacheRand(Misc.ServerFile + "?accao=get_options&value=" + ddListValue);
  16.  
  17. var http_request = Misc.CreateHttpRequest();
  18.  
  19. http_request.onreadystatechange = function(){
  20. var state = http_request.readyState;
  21.  
  22. //pedido completo e respondido com sucesso
  23. if (state == 4 && http_request.status == 200) {
  24. var result = http_request.responseText;
  25.  
  26. var ddSubList = new HTMLControl(ddSubListName);
  27.  
  28. ddSubList.DoDropdownList(eval(result));
  29.  
  30. //voltar a adicionar o event na dropdown "principal"
  31. Events.AddEvent(ddListName, "change", function (){Ajax.UpdateDropdownList(ddListName,ddSubListName);});
  32. Misc.MsgLoading(Ajax.DivLoadingName); //finalizar loading
  33. }
  34. }
  35.  
  36. http_request.open("GET", url, true);
  37. http_request.send(null);
  38. }
  39.  



-> ajax.php - vai receber o pedido, processá-lo e devolver uma resposta, como tinha dito anteriormente, neste snippet esta parte não está elaborada, como poderão ver as respostas estão hard-coded, mas aqui podem por ex. ir buscar os valores a uma base de dados, xml, txt, [you name it] ...; porém coloquei-o só para que possam ver o formato com que terá de ser retornado o objecto json
  1. <?php
  2. // ficheiro responsável pela comunicação com a base de dados
  3. // e devolve as respostas aos pedidos
  4. $accao=$_GET["accao"];
  5.  
  6. if($accao=="get_options"){
  7. $value=$_GET["value"];
  8.  
  9. if($value=="japao"){
  10. $result = "
  11. ({
  12. \"options\": [
  13. {\"value\": \"\",\"description\": \"(escolha um item)\"},
  14. {\"value\": \"aikido\",\"description\": \"Aikido\"},
  15. {\"value\": \"kendo\",\"description\": \"Kendo\"},
  16. {\"value\": \"sumo\",\"description\": \"Sumo\"},
  17. {\"value\": \"shurikenjutsu\",\"description\": \"Shurikenjutsu\"}
  18. ]
  19. });
  20. ";
  21. }
  22.  
  23. else if($value=="china"){
  24. $result = "
  25. ({
  26. \"options\": [
  27. {\"value\": \"\",\"description\": \"(escolha um item)\"},
  28. {\"value\": \"tai_chi_chuan\",\"description\": \"Tai chi chuan\"},
  29. {\"value\": \"shaolin_kung_fu\",\"description\": \"Shaolin kung fu\"},
  30. {\"value\": \"shuai_jiao\",\"description\": \"Shuai Jiao\"},
  31. {\"value\": \"wing_chun\",\"description\": \"Wing Chun\"}
  32. ]
  33. });
  34. ";
  35. }
  36.  
  37. else if($value=="korea"){
  38. $result = "
  39. ({
  40. \"options\": [
  41. {\"value\": \"\",\"description\": \"(escolha um item)\"},
  42. {\"value\": \"taekwondo\",\"description\": \"Taekwondo\"},
  43. {\"value\": \"hapkido\",\"description\": \"Hapkido\"},
  44. {\"value\": \"taekyon\",\"description\": \"Taekyon\"},
  45. {\"value\": \"soobak\",\"description\": \"Soobak\"}
  46. ]
  47. });
  48. ";
  49. }
  50. else{
  51. $result = "
  52. ({
  53. \"options\": [
  54. {\"value\": \"\",\"description\": \"(escolha um pais)\"}
  55. ]
  56. });
  57. ";
  58. }
  59. }
  60.  
  61. echo $result; //imprimir/devolver resposta
  62. ?>



-> Init.js - como o nome indica é aqui que tudo começa, neste snippet tem várias funcionalidades: vai preencher a 1ª dropdown, tal não seria necessário, podiamos ter criado a dropdown normalmente com html ou por ex. dinamicamente, porém aqui vamos recorrer à class HtmlControl para a construir, as opções terão de satisfazer um formato json da mesma forma que o fazemos aquando da actualização da 2ª dropdown; serve também igualmente de exemplo, que não é preciso saber Html para construir uma dropdown, apesar do muito fácil que isso seja :); terá também a função de criar o evento "onchange" na dropdown, para que aquando de uma alteração na opção a 2ª dropdown seja actualizada, neste snippet escolhi unicamente o evento "onchange" como exemplo, mas claro que poderão ser outras.
  1. init = function (){
  2. var arrOptions = {
  3. "options": [
  4. {"value": "","description": "(escolha uma opção)"},
  5. {"value": "japao","description": "Japão"},
  6. {"value": "china","description": "China"},
  7. {"value": "korea","description": "Korea"}
  8. ]
  9. };
  10.  
  11. var dropdownlist = "ddList";
  12. var dropdown_sublist = "ddSubList";
  13.  
  14. var ddList = new HTMLControl(dropdownlist);
  15. ddList.DoDropdownList(arrOptions);
  16. Events.AddEvent($(dropdownlist), "change", function (){Ajax.UpdateDropdownList(this.id,dropdown_sublist);});
  17. }
  18.  
  19. Events.AddEvent(window, "load", init);




-> index.htm - guess ^_-
  1. <html>
  2. <head>
  3. <script type="text/javascript" src="Misc.js"></script>
  4. <script type="text/javascript" src="HtmlControl.js"></script>
  5. <script type="text/javascript" src="Events.js"></script>
  6. <script type="text/javascript" src="Ajax.js"></script>
  7. <script type="text/javascript" src="Init.js"></script>
  8. <link rel="stylesheet" type="text/css" href="style.css" media="all" />
  9. </head>
  10. <body>
  11. <h3>Escolha um país e saiba algumas das suas artes marciais</h3>
  12.  
  13. <div id="div_main">
  14. País:
  15. <select name="ddList" id="ddList"></select>
  16. Arte Marcial:
  17. <select name="ddSubList" id="ddSubList">
  18. <option>(escolha um país)</option>
  19. </select>
  20. </div>
  21. <div id="div_loading"></div>
  22. </body>
  23. </html>





Ficam aqui 2 screenshots:






Qualquer erro/ dúvida é só dizer!









clicks: 11840 11840 2007-11-24 2007-11-24 goto mySnippets mySnippets php  Download  Bookmark This Bookmark This