tadarank afiliados

31 janeiro, 2008

Desenhando pontos e linhas com javascript puro (sem canvas)

Bem, infelizmente javascript não tem muitas capacidades de gerar gráficos, linhas, pontos, círculos, etc a não ser com CANVAS (infelizmente não bem suportado por todos os navegadores) ou por POG.

Fazer usando o canvas não teria graça hehe, então fui pro que eu gosto: a velha gambiarra.

Bom, gerar o ponto é fácil:

<style>
.ponto {  background-color: #0000FF; position: absolute; overflow: hidden;}
</style>
<script>
//global que guarda a largura da linha. Quanto maior, mais rápido o processamento.
window['larguraPonto']=2;
function geraPonto(x, y, nome, elempai) {
    //by Micox - www.elmicox.com - 31/01/08
    var pixel = document.createElement('div');
    pixel.id = nome;
    pixel.className = 'ponto';
    pixel.style.width = pixel.style.height = window['larguraPonto'] + 'px'
    pixel.style.left = x + 'px';
    pixel.style.top = y + 'px';
    return elempai.appendChild(pixel);
}
//chamando a função e gerando uma reta vertical
window.onload = function(){ 
 geraPonto(10,4,'ponto1',document.body) 
 geraPonto(10,6,'ponto2',document.body) 
 geraPonto(10,8,'ponto3',document.body) 
 geraPonto(10,10,'ponto4',document.body) 
 geraPonto(10,12,'ponto4',document.body) 
 geraPonto(10,14,'ponto4',document.body) 
 }
</script>

Perceba que eu coloquei algumas características do ponto via CSS e a definição da largura do ponto em uma variável global. Quanto MENOR for o valor da largura do ponto, logicamente irá demorar mais a plotagem do ponto.

Agora pra gerar uma linha inteira terei que usar meus exímios e velhos conhecimentos de matemática geométrica aprendidos no ensino médio hauehea (Vê se eu lembro disso. Lógico que colei do David Betz e dei umas adaptadas).

function geraLinha(x1, y1, x2, y2, nome, elempai) {
    //by Micox - www.elmicox.com - 31/01/08 - adaptado de http://www.davidbetz.net/graphics/
    var longPixel = document.createElement('div');
    if(elempai.constructor==String){ elempai = document.getElementById(elempai);}
    
    if(typeof(window['MicoxLinhas'])=='undefined'){
        window['MicoxLinhas'] = Array(); //este cidadão global irá guardar todas as linhas
    }
    window['MicoxLinhas'][nome] = Array()
    
    var steep = Math.abs(y2 - y1) > Math.abs(x2 - x1);
    if (steep) {
        var t = y1;
        y1 = x1; x1 = t;
        t = y2; y2 = x2;
        x2 = t;    }
        
    var deltaX = Math.abs(x2 - x1);
    var deltaY = Math.abs(y2 - y1);
    var error = 0;
    var deltaErr = deltaY;
    var xStep, yStep, modulo;
    var x = x1, y = y1;
    
    if (x1 < x2) {
        xStep = window['larguraPonto'];
        modulo = +1;
    }else {
        xStep = -window['larguraPonto'];
        modulo = -1;
    }
    
    if(y1 < y2) { yStep = window['larguraPonto']; }
    else { yStep = -window['larguraPonto']; }
    
    var nomeP = nome + x + '-' + y;
    
    if(steep) { window['MicoxLinhas'][nome][x] = geraPonto(y, x, nomeP, elempai);    }
    else { window['MicoxLinhas'][nome][x] = geraPonto(x, y, nomeP, elempai);    }
    
    var fim = modulo * x2;
    
    while( modulo * x < fim) {
        x = x + xStep;
        error = error + deltaErr;
        if(2 * error >= deltaX) {
            y = y + yStep;
            error = error - deltaX;
        }
        nomeP = nome + x + '-' + y;
        if(steep) { window['MicoxLinhas'][nome][x] = geraPonto(y, x, nomeP, elempai);    }
        else { window['MicoxLinhas'][nome][x] = geraPonto(x, y, nomeP, elempai);    }
    }
    return window['MicoxLinhas'][nome];
}

//brincando de desenhar
window.onload = function(){
 geraLinha(20,120,30,100,'minhaLinha1',document.body)
 geraLinha(30,100,60,100,'minhaLinha2',document.body)
 geraLinha(60,100,90,80,'minhaLinha3',document.body)
 geraLinha(90,80,130,80,'minhaLinha4',document.body)
 geraLinha(130,80,160,100,'minhaLinha5',document.body)
 geraLinha(160,100,210,105,'minhaLinha6',document.body)
 geraLinha(210,105,220,120,'minhaLinha7',document.body)
 geraLinha(220,120,20,120,'minhaLinha8',document.body)
 //agora só faltam as rodas haehaheuhaeu
}

Pronto, agora só falta fazer funções pra elipses e curvas hauheuhae. Não tô afim de brincar disso hoje não. Algum dia eu ou alguém faz uma função pra isso.

Percebam, senhores, que coloquei a opção de nomes nas linhas e pontos e coloquei elas dentro de um pai qualquer. Pra quê? Ué, pra poder apagar e mover as ditas cujas.

As funções de apagar:

function removePonto(nomeOuRef){
    //recebe o ID do ponto ou a referencia ao objeto HTML
    if(nomeOuRef.constructor==String){    nomeOuRef = document.getElementById(nome);    }
    nomeOuRef.parentNode.removeChild(nomeOuRef)
    try { delete nomeOuRef; } catch(e) { nomeOuRef = null }
}
function removeLinha(nomeOuRef){
    //recebe o ID da reta ou a referencia ao objeto array
    if(nomeOuRef.constructor==String){ nomeOuRef = window[nomeOuRef]; }
    for(var i in nomeOuRef){
        removePonto(nomeOuRef[i])
        try { delete nomeOuRef[i]; } catch(e) { nomeOuRef[i] = null }
    }
    try { delete nomeOuRef; } catch(e) { nomeOuRef = null }
}

As funções de mover nem precisava colocar aqui pois é aquele básico esquema de mover Divs:

function move(quem){
 //by Micox - www.elmicox.com - 30/01/08
 if(quem.constructor==String){ quem = document.getElementById(quem); }
 //movendo
 window['move'+quem.id] = setInterval( function(){ 
   quem.style.left = (quem.offsetLeft + 5) + 'px'
  }, 50);
}
function para(quem){
 //by Micox - www.elmicox.com - 30/01/08
 if(quem.constructor==String){ quem = document.getElementById(quem); }
 if(typeof(window['move'+quem.id])=='number'){
  clearInterval(window['move'+quem.id])
 }
}

Agora veja um exemplo completo e meu opalão se movimentando aqui.

- "Porra mico, que mané você heim? Não é mais fácil abrir um programa de imagens qualquer e desenhar diboas?"

- Sim meu caro cidadão, porém, digamos que você queira fazer um fluxograma em javascript (aqui você vê o fluxograma finalizado). E aí? Nunca se sabe quando vamos precisar de algo, como diria George Boole.

Té a próxima, malucada.

Gostou da dica acima? Então clica nos botões de compartilhamento abaixo e me ajude a dica a subir no Google.

17 janeiro, 2008

cssQuery - substituto ao getElementsById e getElementsByTagName

Todo mundo que programa em javascript se cansa de ter que digitar "document.getElementById" ou "document.getElementsByTagName" (ufa, cansei) toooooooda vez que quer selecionar determinado elemento ou grupo de elementos. É ou não é?

Então, após 3 digitadas destes métodos, agente vai lá e programa uma funçãozinha pra simplificar isso. É ou não é?

Na net existem infindáveis funções pra substituir o 1 ou o 2 (não vou digitar tudo denovo não heahe). Todo mundo tem sua velha função $() ou gE() ou gEid(). É ou não é?

Mas as funções que fazem isso "mais mió de bão" estão dentro de frameworks. O que é uma pena pra quem não usa frameworks.
No meu pouco conhecimento, a melhor atualmente é a do jquery que guenta seletores CSS como parâmetro e outros seletores mó bizarros.

Se você não sabe as facilidades dos seletores CSS, dê uma estudada.

O objetivo deste post do mico é mostrar uma ótima solução pra você que não usar frameworks ou cujo framework ou função não suporte fazer a seleção usando seletores CSS:

cssQuery() do Dean Edwards.

"getElementsByTagName? Pah!"
É assim que o ultra-top-master de javascript começa a explicação (mico paga pau).

Sintaxe:

elements = cssQuery(selector [, from]);

Exemplos:

// retorna todos os parágrafos que são filhos diretos de body
var tags = cssQuery("body > p");

// retorna todos os elementos que tenham o atributo 'href'
var tags = cssQuery("[href]");

// retorna os elementos que o atributo 'href' é igual a '#'
var tags = cssQuery("a[href='#']");
// procura todas as imagens dentro dos links retornados acima
var images = cssQuery("img", tags);

// pega todas as listas
var tags = cssQuery("dl,ol,ul");

// até em xml externos
var tags = cssQuery("my|:root>my|link", myXMLDoc);

// você entende isso?
var complex = "p>a:first-child+input[type=text]~span";
var tags = cssQuery(complex);

Seletores suportados:

    *
    E
    E F
    E > F
    E + F
    E ~ F
    E.warning
    E#myid
    E:link
    E:first-child
    E:last-child
    E:nth-child(n)
    E:nth-last-child(n)
    E:only-child
    E:root
    E:lang(fr)
    E:target
    E:enabled
    E:disabled
    E:checked
    E:contains("foo")
    E:not(s)
    E[foo]
    E[foo="bar"]
    E[foo~="bar"]
    E[foo^="bar"]
    E[foo$="bar"]
    E[foo*="bar"]
    E[foo|="bar"]

Guentado no IE, FF, OP, Netscape e Safari.

E aí? Vai trocar suas velhas $() ??

//Há uma lenda aí dizendo que o próximo Firefox vai suportar o velho $() . Será? Procurei um link e não achei. More informations please.

Gostou da dica acima? Então clica nos botões de compartilhamento abaixo e me ajude a dica a subir no Google.

08 janeiro, 2008

Contornar vários bugs do IE numa tacada só

Dean Edwards é o cara.
Pros poucos aqui que não conhecem o site dele, dêem uma visitada geral. Só coisa boa.

Bom, hoje vou me focar na biblioteca IE7 que ele soltou esse ano. Esta biblioteca, magicamente, contorna vários bugs do Internet Explorer e deixa os IE 5, 6 e 7 bem parecidos com o IE8 (ou com o IE 7, você escolhe).

Como assim?

Bem, veja só a descrição:

IE7 is a JavaScript library to make MSIE behave like a standards-compliant browser. It fixes many CSS issues and makes transparent PNG work correctly under IE5 and IE6.

  • supports the following CSS selectors:
    • parent > child
    • adjacent + sibling
    • adjacent ~ sibling
    • [attr], [attr="value"], [attr~="value"] etc
    • .multiple.classes (fixes bug)
    • :hover, :active, :focus (for all elements)
    • :first-child, :last-child, only-child, nth-child, nth-last-child
    • :check, :disabled, :enabled
    • :empty, :contains(), :not()
    • :before/:after/content:
    • :lang()
  • supports imported style sheets
  • preserves the cascade of the style sheet
  • does not alter the document structure
  • does not repeatedly query the DOM tree using JavaScript
  • uses pure CSS to enforce style sheet rules
  • supports the W3C box model in both standards and quirks mode
  • supports fixed positioning (flicker free)
  • supports overflow:visible
  • supports min/max-width/height
  • fixes broken (X)HTML elements (abbr, object)
  • standardised forms behavior
  • supports PNG alpha transparency
  • lightweight script (11KB)
  • works for Microsoft Internet Explorer 5+ (Windows only)

Tudo isso apenas adicionando o seguinte script no seu XHTML:

<!--[if lt IE 8]>
<script src="http://ie7-js.googlecode.com/svn/version/xx.x/IE8.js" type="text/javascript"></script>

<![endif]-->

Pronto, agora é só usar nos seus novos sites e reduzir a queda de cabelo por causa do IE.
Mas antes, dê uma passadinha lá nos site do projeto, da atualização 2.0 e do google code onde está hospedado e veja as formas corretas de usar.
Depois diga aqui suas experiências (boas ou ruins) com o script :) .

Gostou da dica acima? Então clica nos botões de compartilhamento abaixo e me ajude a dica a subir no Google.

Resultado! Concursos