InnerHTML em Select Option

Postado por Micox - Náiron J. C. G..

29 Janeiro, 2007

Opa.

Seguindo uma postagem do Julio Greff sobre o velho problema (bug) do IE ao trabalhar com innerHTML e a tag select, vou mostrar aqui minha solução que eu já tinha feito na época da minha função simples pra ajax.

Edit 28/08/2007: Segunda versão corrigindo bugs pra ativar o selected, classes e styles no IE também

Pequena explicação do problema: às vezes, é necessário agente preencher uma tag select com options através de innerHTML. Pra variar, o IE dá problema com isso. Tá certo que innerHTML não é uma propriedade DOM padrão, mas se o Internet Explorer decidiu implementar ela, deveria, pelo menos, ter implementado direito hehe. Bah, deixa de reclamação mico.

Exemplo:

document.getElementById("meu_select").innerHTML = "<option value='1'>não</option> <option value='2'>funfa</option>"; 

O script acima deveria colocar dentro da select chamada "meu_select" duas opções ("não" e "funfa"). Só que isso não funfa no IE. O jeito certo então é adicionar através de appendChild!!!

Mas, calma, não se desespere, não será necessário você ficar quebrando a cabeça com infinitos appendChild. O Mico resolveu o problema pra você. Basta adicionar minha função abaixo no seu script e chamá-la passando 2 parâmetros: o ID do select que você quer preencher e o innerHTML que você quer colocar dentro deste select.

A função vai cuidar de tudo, como se você estivesse setando através da propriedade innerHTML mesmo, inclusive os atributos do option.

Exemplo de uso (baseado no exemplo anterior que não funfava):

var inner = "<option value='1'>Agora</option> <option value='2'>funfa</option>"; 
select_innerHTML(document.getElementById("meu_select"),inner);

A função mágica que faz isso. Adicione copie no seu script:

function select_innerHTML(objeto,innerHTML){
/******
* select_innerHTML - corrige o bug do InnerHTML em selects no IE
* Veja o problema em: http://support.microsoft.com/default.aspx?scid=kb;en-us;276228
* Versão: 2.1 - 04/09/2007
* Autor: Micox - Náiron José C. Guimarães - micoxjcg@yahoo.com.br
* @objeto(tipo HTMLobject): o select a ser alterado
* @innerHTML(tipo string): o novo valor do innerHTML
*******/
    objeto.innerHTML = ""
    var selTemp = document.createElement("micoxselect")
    var opt;
    selTemp.id="micoxselect1"
    document.body.appendChild(selTemp)
    selTemp = document.getElementById("micoxselect1")
    selTemp.style.display="none"
    if(innerHTML.toLowerCase().indexOf("<option")<0){//se não é option eu converto
        innerHTML = "<option>" + innerHTML + "</option>"
    }
    innerHTML = innerHTML.toLowerCase().replace(/<option/g,"<span").replace(/<\/option/g,"</span")
    selTemp.innerHTML = innerHTML
      
    
    for(var i=0;i<selTemp.childNodes.length;i++){
  var spantemp = selTemp.childNodes[i];
  
        if(spantemp.tagName){     
            opt = document.createElement("OPTION")
    
   if(document.all){ //IE
    objeto.add(opt)
   }else{
    objeto.appendChild(opt)
   }       
    
   //getting attributes
   for(var j=0; j<spantemp.attributes.length ; j++){
    var attrName = spantemp.attributes[j].nodeName;
    var attrVal = spantemp.attributes[j].nodeValue;
    if(attrVal){
     try{
      opt.setAttribute(attrName,attrVal);
      opt.setAttributeNode(spantemp.attributes[j].cloneNode(true));
     }catch(e){}
    }
   }
   //getting styles
   if(spantemp.style){
    for(var y in spantemp.style){
     try{opt.style[y] = spantemp.style[y];}catch(e){}
    }
   }
   //value and text
   opt.value = spantemp.getAttribute("value")
   opt.text = spantemp.innerHTML
   //IE
   opt.selected = spantemp.getAttribute('selected');
   opt.className = spantemp.className;
  } 
 }    
 document.body.removeChild(selTemp)
 selTemp = null
}

Bugs? Grita nos comments ae. Dúvidas? Joga no fórum e me avisa.
Não se esqueça de conferir também a solução do Julio para este problema.

Marcadores: ,

E-mail Newsletter Feed RSS Resultado! Concursos Shopping Resultado

Não mande dúvidas nos comentários ou no meu e-mail. Mande elas para o fórum de desenvolvedores Webly. Tem mais gente lá gabaritada a responder e você não fica dependendo só do mico.


Comenta aí! Não cai o dedo e me incentiva a escrever mais. (12 comentários)





12 Comentários:

Blogger Rafael disse... 29 Janeiro, 2007 19:23  
É, não é só no XHTML e CSS que a Microsoft faz bonito, ela consegue ser diferente também no JS. Haja paciência, né? Magnífica solução!
Estou comeeçaando (a passos de tartaruga) a minha aprendizagem de AJAX, mas o que mais me intriga, de tudo isso, é o fato de perdermos tanto tempo arrumando coisinhas pois o IE faz tudo como ele mesmo quer. É uma lástima, mas "ESTAMOS AQUI PRA ISSO".

Abraços!
Anonymous JulioGreff disse... 30 Janeiro, 2007 17:17  
Engenhoso... Infelizmente, o tal do innerHTML é uma tentação. E muito mais rápido do que appendChild. E nem pra implementar direito, como o mico disse. Funciona legal, só não deixa a W3C ver isso...
Blogger Cau disse... 31 Janeiro, 2007 15:27  
Fala Mico, beleza?
Cara hoje vi este post e o do Julio. Uso outra forma para preencher os selects, option a option, usando o método add, nativo do objeto select.
Talvez interesse ver outra forma...

function addOption(selec,val,tex) {
var opt = document.createElement('option');
opt.value = val;
opt.text = tex;
try { selec.add(opt, null); } // NS FF
catch(e) { selec.add(opt); } // IE
}

Abraço, Cau
Anonymous Micox disse... 31 Janeiro, 2007 16:19  
@rafael
A MS fez muito no passado pelo JavaScript e pelo CSS, mas hoje em dia tá manezando ao não respeitar os padrões

@Julio
hehe, é verdade. De qualquer forma o innerHTML não é padrão, e dentro da minha função eu uso o innerHTML.
Mas é só uma facilidade ao mexer com o select. heheh

@Cau
Beleza, valeu cau. Depois insiro esta nova forma dentro da minha função pra ver se fica melhor :)
Blogger Fabrício disse... 15 Fevereiro, 2007 11:30  
Tem essa tb, que é padrão para todos, sem isso de ifs //para IE, //para FF, Opera...

function addOption(id, sText, sValue) {
var obj = document.getElementById(id);
obj.options[obj.length] = new Option(sText, sValue);
}

Falou,
Fabrício Magri
Blogger Roberson disse... 24 Fevereiro, 2007 02:41  
Daew Micox..
Eu criei esta funcao aqui, baseando-me no mootools, acho que ela resolve o problema do innerHTML para select do Internet Explorer..
pelo menos pra mim resolveu!

Vou colocar aqui duas versoes:
1ª - baseada no mootools
2ª - convertida para ser usada sem o mootools

Obs: Quando for copiar a funcao, substitua a string de valor (TAG SELECT) pela tag select , e onde esta (TAG /SELECT) pela tag /select .
*Mudanca feita porque o blog nao aceita tag select no comentario.

Testa aew e me diz se ela faz o mesmo que a sua, valeu pela funcao, tive a ideia de fazer a minha quando vi a sua!

id : id do select.
html: html com as tags option.

1ª:

function innerSelect(id,html)
{
var sel = $(id);
html = '(TAG SELECT)'+html+'(TAG /SELECT)';
var temp = new Element('div');
temp.setHTML(html);sel.setHTML('');
temp.getElements('option').each( function(opt){opt.injectInside(sel);} );
}

2ª:
function innerSelect(id,html)
{
var sel = document.getElementById(id);
html = '(TAG SELECT)'+html+'<(TAG /SELECT)';
var temp = document.createElement('div');
temp.innerHTML = html;
sel.innerHTML = '';
var options = temp.getElementsByTagName('option');
while (options.length)
{
sel.appendChild(options[i]);
}
}
Blogger Micox - Náiron J. C. G. disse... 25 Fevereiro, 2007 08:26  
@Fabricio e Roberson
As funções de vocês fazem QUASE a mesma coisa. Só faltou pegarem os atributos dos options tipo "selected".

Valeus pelas contribuições ae.
Blogger Roberson disse... 25 Fevereiro, 2007 11:00  
Nao micox.. tipow se vc passar la o option id="opt1" selected="selected" value="32"> Nao Funfa /option>
corrigindo as tags ali eh claro..
ele vai pegar todos os atributos passados (no caso id, selected, e value.. contanto q seja passado assim na html!
esclarecido?
abraços..
Blogger ramon disse... 13 Março, 2007 14:48  
Companheiro, tive o mesmo problema que você ao preencher um SELECT com Ajax. A Microsoft se supera a cada dia.
Sua solução foi muito boa.
Blogger Micox - Náiron J. C. G. disse... 23 Março, 2007 08:29  
@roberson
Demorei pra responder mas saquei sua explicação. Valeus.
Anonymous diego disse... 06 Maio, 2008 15:15  
a "função mágica" funcionou perfeitamente no ie mas nao funcionou no firefox. alguem tem alguma ideia?
Anonymous GGiovani disse... 30 Janeiro, 2009 15:13  
TIRE O TOLOWERCASE pq ele converte o texto para minusuulo

Escreva seu comentário (Leia abaixo).

Deixe seu email se quiser resposta por email também, pois o sistema de comentários do Blogger não me informa :( ... Ah, também pode deixar o endereço do seu blog ou site no comentário.
Já estou em outro sistema de blog melhor (wordpress). Se quiser comentar lá também :)
Dúvidas, só no fórum Webly.

Links para este post:

<< Ir à página principal e ver as novas postagens.

El Micox - Alguns direitos resevados - Licença Creative Commons

Veja! Este é apenas um espelho do blog real elmicox.com. Assinando aqui, na verdade você está assinando lá.