Categorias
Tecnologia

Como utilizar Ajax no WordPress

Hoje vou dar uma dica de como utilizar ajax no WordPress.

Precisei fazer uma chamada assíncrona em uma página de template do WordPress em um projeto que estive trabalhando e fui pesquisar como funcionava. O WordPress tem seu jeitinho todo especial de executar requisições XHR.

O primeiro passo é escrever uma função (no arquivo functions.php) para executar o que você quiser que o backend faça nessa chamada Ajax. No caso do exemplo desta publicação estou enviando um email.

// Actions to send mail
add_action('wp_ajax_sendMyMail', 'sendMyMail');
add_action('wp_ajax_nopriv_sendMyMail', 'sendMyMail');

// Sending the email
function sendMyMail() {
  global $wpdb;

  $message = "Form data:\n\n Name: {$_POST['name']}";
  if (wp_mail('email@email.com', 
              'Title', 
              $message, 
              array('Cc:email@copy.com'), 
              array())) {
  	echo 'success';
  } else {
  	echo 'error';
  }

  die();
}

Linha por linha da função no functions.php

Usando o add_action do WordPress, registramos nossa função. No primeiro wp_ajax_sendMail estamos registrando a função para utilização no painel Admin do WordPress e com o wp_ajax_nopriv_sendMail registramos a função para utilização no frontend, onde o usuário não estará logado.

O formato desses dois tipos de actions específicas para ajax sempre devem começar com wp_ajax_(action) ou wp_ajax_nopriv_(action).

// Actions to send mail
add_action('wp_ajax_sendMyMail', 'sendMyMail'); 
add_action('wp_ajax_nopriv_sendMyMail', 'sendMyMail');

Depois vem a função em si, com as ações que você quiser. Como eu já disse, nesse exemplo é o envio de um email.

// Sending the email function 
sendMyMail() {
 global $wpdb;
 $message = "Form data:\n\n Name: {$_POST['name']}";

 if (wp_mail('email@email.com',
             'Title',
             $message,
             array('Cc:email@copy.com'),
             array())) {
  echo 'success';
 } else {
  echo 'error';
 }

No final usamos o die() do PHP para encerrar o processo.

 die();
}

A requisição Ajax

Agora vamos à chamada assíncrona no Javascript.

Fazemos uma chamada com o método $.ajax do jQuery normalmente, mas a diferença está na URL que utilizaremos nela e em um item que precisa ser adicionado nos dados enviados para o servidor.

$.ajax({
 type:"POST",
 url: "/wp-admin/admin-ajax.php",
 data: {
  action: 'sendMyMail',
  name: $('input[name=name]').val()  
 },  
 success: function(data){
  console.log(data)
 }
});

A URL deve ser sempre /wp-admin/admin-ajax.php e o nome da ação que você registrou no functions.php entra como um dado com o nome action junto com o resto dos dados que você irá mandar para o servidor.

url: "/wp-admin/admin-ajax.php",
data: {
 action: 'sendMyMail',
 name: $('input[name=name]').val() 
 }

E voilá!

Deixe suas dúvidas ou opiniões nos comentários abaixo.

Nos vemos na próxima.

Categorias
Tecnologia

Lendo RSS Feed somente com Javascript (jQuery)

Eu construi uma página estática em HTML, CSS e JS para ser uma espécie de portfólio e cartão pessoal para mim e queria colocar uma seção com os artigos deste blog nela. A melhor maneira de acessar esses artigos sem muito esforço é usando o RSS Feed do blog.

Mas a página é “estática”, então eu poderia usar no máximo o Javascript para ler o Feed do blog. Uma opção seria acessá-lo via Ajax e processar os dados em seguida, mas se o Feed for de outra origem (domínio diferente, que não era o meu caso, mas pode ser o seu) ia acabar esbarrando em um erro de segurança (CORS Error) e não funcionaria.

Então encontrei uma solução (no link de referência no final do artigo), usar uma API do Google que lê um Feed e retorna um JSON com as informações dele.

Segue abaixo uma versão do código que estou utilizando na página, totalmente comentado.

Os items que temos disponíveis para acesso, como mostra a imagem abaixo, são o autor, categorias e tags, o conteúdo inteiro em HTML, um pequeno snippet do conteúdo em texto puro, a URL do artigo, a data de publicação e o título. Eu senti falta do retorno das mídias, como fotos, por exemplo, mas se for necessário a opção seria pegá-las do próprio HTML que retorna em “content“.

É isso aí, qualquer dúvida ou sugestão deixe nos comentários abaixo. Para ver esse código em funcionamento acesse o site.

Referência: http://pt.stackoverflow.com/a/65758

Categorias
Tecnologia

Usando Grunt para compilar SCSS (Sass)

O Grunt é um gerenciador de tarefas JavaScript. O conheci pela primeira vez quando utilizei o Yeoman para desenvolver um projeto em AngularJS (leia mais).

O Sass é uma linguagem de extensão de CSS, que se auto-intitula “CSS com superpoderes”.

Precisei começar um novo projeto de frontend montando apenas os HTMLs, JavaScripts e CSSs das páginas. Então resolvi conhecer melhor o Grunt e o Sass.

Percebi que dominar essas ferramentas gera dezenas de possibilidades novas para o desenvolvimento frontend. Claro que ainda não dominei, mas vou escrever um pouco sobre o que já aprendi.

Obs: Para todos os comandos abaixo estou utilizando a linha de comando (console) do Linux.

Para instalar o Sass é necessário o package manager do Ruby, o RubyGems.

sudo su -c "gem install sass"

Para instalar o grunt-cli é necessário o package manager do Node.js, o npm. Aproveito para já instalar os pacotes que vou utilizar: grunt-contrib-sass e grunt-contrib-watch.

npm install grunt grunt-contrib-sass grunt-contrib-watch

Estou usando o Bootstrap nesse projeto, então é necessário instalar o bootstrap-sass pelo npm.

npm install boostrap-saas

Minha estrutura de diretórios será a seguinte:

  • project/
    • node_modules/
    • public/
      • css/
      • img/
      • js/
      • index.html
    • sass/
      • style.scss
    • Gruntfile.js
    • package.json

No arquivo Gruntfile.js configuramos todas as tarefas que o Grunt vai executar. No caso desta publicação faremos a preprocessamento do SCSS para CSS.

Todas as tarefas do Grunt são executadas na linha de comando (console) precedidas por “grunt”, como por exemplo “grunt watch” ou “grunt build”.

Primeiro configurei o Sass para compilar para o ambiente de desenvolvimento, nesse caso o CSS não ficará comprimido, para que eu possa vê-lo em ação. No caso da configuração para ambiente de produção ele será comprimido.

Então configuro a tarefa do grunt-watch, ela acionará a tarefa “sass:dev“, que configuramos no passo anterior, a cada mudança que eu fizer aos arquivos *.scss. Isso serve para que eu não precise rodar um comando grunt manualmente a cada alteração no SCSS, o que seria contraproducente.

Obs: Para que isso aconteça é preciso deixar o comando “grunt watch” rodando na linha de comando (console).

No final do arquivo registro as tarefas com o registerTask. No caso apenas “grunt build“, que será usado para gerar o CSS final comprimido para produção, pois a tarefa que gera os arquivos não-comprimidos para ambiente de desenvolvimento já será chamada pelo grunt-watch e não precisa ser registrada novamente.

Estas tarefas registradas ao final do arquivo servem para agregar várias tarefas a um único comando. Assim quando você precisar rodar tudo de uma vez para gerar a versão de produção, você rodorá apenas “grunt build” e todas as tarefas da lista serão executadas. No nosso caso temos apenas o Sass por enquanto, mas futuramente podemos ter diversas tarefas a serem executadas para gerar os arquivos de prod.

Vou falar mais sobre Grunt e Sass no futuro. Se tiver alguma sugestão ou dúvida sobre o conteúdo desta publicação, dexe um comentário abaixo.

Categorias
Tecnologia

Usando grunt-ng-constant para mudar o endereço da API no build de um app AngularJS

Desenvolvendo pela primeira vez um webapp que consome uma API com AngularJS (e usando o Yeoman e o Grunt para fazer build e para autorefresh durante o desenvolvimento) me deparei com uma questão: Como faria o build dos arquivos para diferentes ambientes? Atualmente este projeto possui os ambientes local (dev), homologação e produção, cada um com seu respectivo endereço de API.

Para atingir esse objetivo, e como essa era minha primeira vez com Angular e com Grunt, pesquisei muito e achei uma solução que funcionou bem.

Usango o pacote grunt-ng-constant eu consigo manter uma constante com a URL de cada ambiente separadamente. Dependendo do comando de build que eu executar no Grunt, terei um resultado diferente nessa constante.

O primeiro passo é instalar o pacote citado. Lembrando que estou utilizando o NPM como gerenciador de pacotes.

npm install grunt-ng-constant --save-dev

Depois temos que configurá-lo no nosso arquivo Gruntfile.js. Aqui segue um exemplo comentado:

Com o Grunt configurado, podemos passar para nosso AngularJS agora.

Dentro do arquivo app.js injetamos o parâmetro ENV no método run e passamos a constante apiBaseURL para o $rootScope, fazendo com que ela fique disponível por todo o app.

Agora você pode usar um service que faça as chamadas de API concatenando seu apiBaseUrl em todos os requests. Como no exemplo abaixo.

Para finalizar, fazemos o build com o seguinte comando:

grunt build:homolog

Podendo subistituir o homolog por develop ou prod (ou deixar sem nenhum, que pegará o padrão prod que definimos no Grunfile.js) e testar seus arquivos no diretório dist. Lembrando que o arquivo config.js será gerado automaticamente durante o build.

Tive uma boa batalha com o Grunt no começo, mas depois que aprendemos como funciona ele se torna um aliado incrível para o desenvolvimento.

Espero que tenha gostado dessa postagem, se tiver alguma dúvida ou comentário deixe abaixo.

Categorias
Tecnologia

Summernote, um editor WYSIWYG super simples para Bootstrap

O Summernote é um editor WYSIWYG muito bom, e simples, para utilizar em aplicações web. Pra quem não sabe o que significa WYSIWYG, vejamos o que nos diz a Wikipedia.

WYSIWYG é o acrônimo da expressão em inglês “What You See Is What You Get”, cuja tradução remete a algo como “O que você vê é o que você obtém” (OQVVEOQVO). Significa a capacidade de um programa de computador de permitir que um documento, enquanto manipulado na tela, tenha a mesma aparência de sua utilização (…)

No nosso caso, estamos falando de aplicações web. O Summernote é um dos editores mais simples que já encontrei e sua instalação foi tão fácil que me surpreendi. Até mesmo para personalizar o upload de imagem foi mais simples do que eu imaginava.

Outros editores WYSIWYG para web muito conhecidos, e que eu já utilizei em alguns projetos, são o CKEditor e o TinyMCE. Apesar de suas instalações não serem complicadas, ambos tem muitos arquivos e exigem um conhecimento mais específico para executar qualquer alteração, principalmente no upload de imagens.

Para utilizar o Summernote é preciso jQuery, Bootstrap e Font Awesome (para os ícones). Com as linhas abaixo você consegue essas dependências funcionando na sua aplicação.

<script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.1/css/bootstrap.min.css" rel="stylesheet">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.1/js/bootstrap.min.js"></script>
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet">

A seguir, basta inserir o CSS e o código JavaScript do Summernote.

<link href="summernote.css" rel="stylesheet">
<script src="summernote.min.js"></script>

Então basta escolher qual é o campo que você deseja transformar em um editor WYSIWYG, adicionar o código de inicialização do Summernote, como no exemplo abaixo, e voilà!

<div id="summernote">Hello Summernote</div>
<script>
$(document).ready(function() {
  $('#summernote').summernote();
});
</script>

Seu campo vai aparecer dessa maneira:

Se você quer personalizar os itens da barra do editor, o tamanho do campo, entre outras coisas, basta ver as features no site do Summernote.

Personalizando o upload de imagens

Ao inserir uma imagem, por padrão, o editor insere os dados da imagem em Base64 ao texto. Mas normalmente não é isso que queremos no nosso código, certo? Então a opção é alterar o padrão para efetuar um upload do arquivo ao ser inserido.

Não vou abordar aqui o script backend por trás do upload, porque isso não tem nada a ver com o editor em questão, vou mostrar apenas como chamamos esse código pelo Summernote.

$(document).ready(function() {
    $('#summernote').summernote({
        onImageUpload: function(files, editor, welEditable) {
            sendFile(files[0],editor,welEditable);
        }
    });
});

function sendFile(file,editor,welEditable) {
    data = new FormData();
    data.append("file", file);
    $.ajax({
        data: data,
        type: "POST",
        url: "url/para/upload/",
        cache: false,
        contentType: false,
        processData: false,
        success: function(url) {
            editor.insertImage(welEditable, url);
        }
    });
}

Primeiro configuramos o callback onImageUpload para chamar nossa função de envio de arquivo. Essa função, a sendFile, cria um novo objeto de formulário pelo javascript e insere o nosso arquivo a ele. Com o método $.ajax do jQuery chamamos nosso script de backend e, mais uma vez, voilà!

Funcionou muito bem pra mim e espero que essas dicas possam ajudar a facilitar a vida de mais pessoas por ai.

Categorias
Tecnologia

Sticky navbar com Bootstrap

Como fixar a barra de navegação do Bootstrap quando a barra de rolagem chegar nela? Essa funcionalidade é chamada de Sticky Navbar.

Utilizando esse código JavaScript abaixo a barra de navegação estática (com a classe .navbar-static-top) passa a ficar fixada no topo da página (classe .navbar-fixed-top) quando a barra de rolagem atinge certa parte da página.

      var num = $('.navbar').offset().top;

      $(window).bind('scroll', function () {
          if ($(window).scrollTop() > num) {
              $('.navbar').addClass('navbar-fixed-top');
              $('.navbar').removeClass('navbar-static-top');
          } else {
              $('.navbar').addClass('navbar-static-top');
              $('.navbar').removeClass('navbar-fixed-top');
          }
      });

A variável num contém a quantidade de pixels do topo até onde a barra de rolagem vai atuar para modificar o estilo da navbar. Neste caso estou utilizando o método offset() do jQuery para verificar a altura da barra de navegação automaticamente.

As classes de navbar descritas acima são originalmente do Bootstrap (testado com o Bootstrap 3.3.2), mas com algumas adaptações pode ser utilizado em qualquer outro CSS, basta alterar os nomes das classes no código.

Esse código foi encontrado nesse JSFiddle e apenas alterei para a utilização do método offset().

Categorias
Tecnologia

Annyang para reconhecimento de voz

Nos últimos dias do ano passado comecei um projeto de chatbot para praticar Python e Flask, chama-se Jarvis. A ideia é que sempre que eu tiver um tempo livre eu adicione algumas coisinhas a mais nele.

Desde o começo eu gostaria que o Jarvis ajudasse na prática da lingua inglesa, principalmente na conversação. Foi por isso que comecei a pesquisar meios de fazer reconhecimento de voz (speech recognition) pela web.

A opção mais comum é a Speech API do Google, entretanto ela tem algumas limitações por ter um largo uso entre os desenvolvedores. Então fui pesquisar se existia outra opção. Nessa pesquisa encontrei o Annyang, um projeto em javascript para adicionar comandos de voz ao seus aplicativos web.

Ele é muito fácil de aplicar ao site, basta adicionar o script ao html e declarar os comandos de voz que o seu site irá atender.

<script src="//cdnjs.cloudflare.com/ajax/libs/annyang/1.4.0/annyang.min.js"></script>
<script>
    if (annyang) {
        // Let's define our first command. First the text we expect, and then the function it should call
        var commands = {
            'show tps report': function() {
                $('#tpsreport').animate({bottom: '-100px'});
            }
        };

        // Add our commands to annyang
        annyang.addCommands(commands);

        // Start listening. You can call this here, or attach this call to an event, button, etc.
        annyang.start();
    }
</script>

É importante adicionar uma verificação lógica na variável annyang antes de tudo, porque se o navegador não for compatível com o reconhecimento de voz seus comandos serão ignorados e não causarão erro algum. Isso pode ser feito porque no código fonte do Annyang a variável é iniciada como false antes de fazer a verificação de suporte do navegador e caso o mesmo não tenha este suporte, ela continuará falsa.

Caso você queira adicionar um comando que possa receber qualquer palavra depois (uma variável) continua sendo muito simples: basta adicionar um asterisco antes do nome da variável e declará-la como parâmetro na função anônima do comando.

var commands = {
    'tell me *chat' : function(chat) {
        $('#question').val(chat);
        $('#the-form').submit();
    }
}

No exemplo acima mostro como estou usando no projeto Jarvis. Basta o usuário pronunciar ‘tell me‘ e a frase que gostaria de dizer em inglês, então o sistema preenche o campo do formulário com a frase e em seguida executa um submit, fazendo com que o Jarvis responda em seguida.

Caso você queira ver o que está acontecendo enquanto ele tenta reconhecer o que você está dizendo, adicione um annyang.debug(); antes do annyang.start();. Isso fará com que ele apresente no seu console Javascript o que está sendo reconhecido em tempo real. Isso é prático porque ele nem sempre consegue reconhecer e você consegue perceber o que pode estar acontecendo.

Opinião

O Annyang funciona muito bem para aquilo que se propõe, que é o reconhecimento de comandos de voz, entretanto nem sempre ele consegue reconhecer uma frase maior, diferente da Speech API do Google, talvez por problemas com a entonação ou a pronúncia. Ainda não experimentei ele com um microfone melhor, apenas com o do meu notebook, e talvez isso faça uma boa diferença na porcentagem de sucesso. Mas ele é tão fácil de implementar que vale a pena experimentar e se divertir com os comandos de voz.

No caso do Jarvis ele não fica tão prático por causa da necessidade de um comando antes de cada frase e para a prática de conversação isso é um pé no saco, mas mesmo assim vou mantê-lo no projeto por enquanto.

Observação: O Annyang não irá funcionar com arquivos locais (acessando via file:///) pois o navegador (pelo menos o Google Chrome) irá bloquear a tentativa do script de acessar o microfone. É preciso testá-lo com um servidor http.