Pegar o elemento script que está sendo escrito

Em um script eu precisava pegar o elemento pai do script que estava escrevendo (parent do elemento script atual), surgiu uma dúvida então de como selecionar o script que eu estava escrevendo e é o que vou compartilhar neste post.

Como o javascript é executado em tempo de carregamento, o último elemento script será o que você está trabalhando, para pegar este elemento é só fazer o seguinte:

var scripts = document.getElementsByTagName( 'script' );
var thisScriptTag = scripts[ scripts.length - 1 ];

A explicação do código:

Primeiro pegamos todos os elementos script da página – como ela só foi carrega até o momento do código, na verdade pegamos todos os elementos script carregados até o momento. A segunda linha pega a última tag script carregada até o momento, que sempre será a que estamos trabalhando.

Com o elemento selecionado é só navegar no DOM da forma que você achar melhor!

Expressão Regular com variável no Javascript

Nesta sábado estava com um problema para fazer uma magia negra com NodeJS, precisava manipular um texto que seria publicado com código parecido com BBCode para identificar a posição de elementos (parecidos com widgets) que deveriam ser substituídos de acordo com seu tipo.

Para isso, precisava identificar o padrão [#tipo_id], como poderiam ser vários tipos de componentes (e como sempre o sistema pode crescer e novos tipos serem adicionados) a melhor forma de trabalhar com isso seria uma expressão regular com uma variável.

Antes eu tinha o seguinte:

var er = new RegExp(/\[#img_.*?\]/g);
var results = minhastring.match(er);

O que eu precisava era que o #img fosse uma variável para que esta rotina de busca e replace pudesse ser transformada em uma função parametrizada, o resultado final:

var er = new RegExp('\\['+ busca +'.*?\\]', 'g');

A sugestão do @knorrium em uma consultoria rápida pelo Twitter e sem saber exatamente o que eu precisava foi o uso do eval(), testei e funcionou, mas esta modo diferente de uso do new RegExp com dois parâmetros string que o @manuWell sugeriu ficou mais elegante. 

E você, como faria uma Regexp com variável no javascript?

Dicas: jQuery performance

Duas coisas que todo o bom desenvolvedor deve se preocupar: segurança e performance.

Comecei a me preocupar e estudar mais a fundo performance em PHP quando passei a ter problemas com o crescimento do And After, para isso desenvolvi um sistema de cache inteligente utilizando o cache do Code Igniter, que aumentou muito a performance de entrega das páginas – e mesmo assim tem muito que pode melhorar.

Performance no front-end

Com a reduação dos custos computacionais (cloud, balance e servidores mais acessíveis) os problemas de processamento do backend muitas vezes são resolvidos com o "liga mais máquina", mas os problemas de performance no front-end são sentidos pelo usuário – e não temos controle sobre o computador do usuário.

A redução do custo do acesso a internet banda larga (internet 1Mb a R$35,00) permite que carreguemos mais código e imagens com mais qualidade sem prejudicar muito a entrega, mas ainda temos dois pontos principais de otimização de sites front-end que independem de banda ou do servidor:

  1. Renderização do código
  2. Performance do javascript

A forma e ordenação de como o HTML é escrito definem como ele será renderizado – e cada browser fará isso de uma forma, por isso é muito importante seguir as boas práticas e recomendações da W3C para estar preparado para o futuro, e não preso aos navegadores do passado.

Assim como o html, cada navegador tem a sua forma (ou engine) para lidar com javascript, o que diferencia muito a performance de algumas funções em um navegador ou outro – achar a forma que atende melhor seus usuários (sem ficar preso a navegadores velhacos) é o que eu vejo como melhor opção.

Se você quer entender um pouco mais sobre javascript recomendo a leitura dos slides sobre performance em javascript que postei anteriormente, os slides deste post tratam exclusivamente da biblioteca jQuery.

jQuery performance

Os slides abaixo apresentam diversos testes de performance com a biblioteca jQuery, em diversos navegadores. 

 

Uma boa forma de mensurar e testar seu código é criando uma rotina de testes de performance, que pode ser usando alguma biblioteca (ainda não usei para teste de performance) e o "modo macho", criando um cronômetro em javascript e marcando o tempo de execução de loops com cada função que você quer testar.

Validação simples de formulário com jQuery

Normalmente opto pelo uso do jQuery Validate para validação de formulário (veja como ignorar o jQuery Validate), mas em uma tela que estava trabalhando eu tinha vários formulários que abriam em modal (usando o PrettyPhoto) e eram manipulados antes da abertura dependendo das ações do usuário naquela tela.

Ao invés de usar o validate achei que seria mais simples implementar uma função para validação, seguindo a seguinte regra:

  • Os elementos com a classe "required" devem ser obrigatórios
  • Adicionar a classe "error" aos elementos obrigatórios não preenchidos
  • Exibir um elemento com a mensagem de erro do formulário
  • Retornar true se passar na validação

A função ficou bastante simples e poderia ser escrita facilmente sem o uso do jQuery.

Validação sem plugin

function validateForm(form){
    var err = 0;
    form.children('.required').each(function(){
        if($(this).val() == '' || $(this).val() == null){
            $(this).addClass('error');
            form.children('.error_form').show();
            err++;
        }
    })
    if(err == 0)
        return true
}

 

Update

Seguindo a dica do Chris, a validação do exemplo acima pode ser substituída por uma expressão regular que verifica se a string é vazia no javascript, como no exemplo abaixo:

function notNull (x){
        if(a!="" && !(a.match(/^\s+$/))){
            return true;
        }else{
            return false;
        }
}

A função segue a seguinte lógica:

  1. Recebe como parâmetro um objeto do jQuery (optei por isso ao invés do id ou classe pois meu código já tinha uma variável com o form selecionado por questões de performance.
  2. Cria uma variável chamada err com valor 0, que irá contabilizar os erros (caso exitam).
  3. Percorre todos os elementos do formulário e busca pelos que tenham a classe "required", percorrendo todos estes e:

    1. Verifica se o valor do elemento é vazio ou null, se for adiciona a classe "error" no elemento e mostra o elemento com classe "error_form" que está no formulário (caso exista).
    2. Soma 1 a variável err.
  4. Se depois de percorrer todos os elementos com classe "required" nenhum erro for contabilizado retorna true.

 

Seria possível retornar também o número de erros em caso de false, modificando o final da função para:

    if(err == 0)
        return true
    else
        return err;

Sei que validação já é um assunto um pouco "manjado" de javascript e muita gente opta pelos plugins, resolvi compartilhar para mostrar como funciona e exeplificar que nem sempre é necessário a gente inserir plugin para tudo o que vamos fazer…

Seletor por classe no javascript

Vi alguns questionamentos em fóruns sobre seletor de classe em javascript e resolvi compartilhar uma solução do fórum, que extende o document para que seja possível fazer seleção de elementos por classe sem a necessidade de usar uma biblioteca (jQuery, por exemplo) para isso.

Já postei um exemplo em HTML5 da selector API (querySelector), mas como isso só é suportado por browsers modernos a solução abaixo quebra o galho (e se getElementsByClassName for nativa do navegador ele usa a função nativa).

Função getElementByClassName

A função abaixo permite que você user document.getElementByClassName('nomeDaClasse') para fazer seletores sem o uso de nenhuma biblioteca.

if (document.getElementsByClassName == undefined) {
    document.getElementsByClassName = function(className)
    {
        var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
        var allElements = document.getElementsByTagName("*");
        var results = [];

        var element;
        for (var i = 0; (element = allElements[i]) != null; i++) {
            var elementClass = element.className;
            if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
                results.push(element);
        }

        return results;
    }
}

 

Na maioria dos projetos uso jQuery, mas tem alguns que o javascript é tão simples que não é necessário os 29Kb – e esse seletor de classes já quebra o galho. 🙂

Solução de um colaborador do DevShed.