Javascript – o método call() e apply()

Todas as funções do javascript possuem alguns métodos como toString(), call() e apply(). Antes de explicar o método function.call() vou exemplificar o funcionamento das funções e escopos, que acredito que isso facilite o entendimento.

Exemplo de código:

var url = 'andafter.org';
function f(){
    console.log(this);
    console.log(this.url);
}
f();

Nesse código eu seto uma variável global url, e quando chamo a função f dou um log em "this" (é a window), então quando chamo this.url o retorno é a variável instanciada fora da função.

O método call()

O método function.call() permite você dizer em qual escopo (essa é a nomenclatura certa? comentem suas opiniões) uma função deve ser executada.

Voltando ao exemplo de código anterior:

var url = 'andafter.org';
var site = { url : 'odesenvolvedor.com.br' };
function f(){
    console.log(this.url);
}
f.call(site);

O function.call() define o que será o "this" dentro da função, e este deve ser passado como parâmetro para o método call.

 

Método call com parâmetros

No exemplo anterior não fizemos uso de parâmetros, apenas do "this". Mas o método call pode receber a partir do segundo parâmeto (o primeiro sempre será o escopo que será atribuído ao this) os parâmetros que serão passados para a função.

var url = 'andafter.org';
var site = { url : 'odesenvolvedor.com.br' };
function f(p1, p2){
    console.log(this.url + ' - ' + p1 + ' - ' + p2);
}
f('aprendendo javascript', 'no andafter!');
f.call(site, 'estudando códigos', 'no desenvolvedor');

O método function.apply()

O método function.apply() tem o mesmo funcionamento do function.call() com uma diferença na forma dos parâmetros, o segundo parâmetro sempre deverá ser um array, contendo todos os parâmetros que serão enviados para a função.

O primeiro parâmetro continua sendo o escopo onde sua função será executada.

var url = 'andafter.org';
var site = { url : 'odesenvolvedor.com.br' };
function f(p1, p2){
    console.log(this.url + ' - ' + p1 + ' ' + p2);
}
f('aprendendo javascript', 'no andafter!');
f.apply(site, ['estudando códigos', 'no desenvolvedor']);

Agora você já sabe como definir em qual escopo uma função será executada, e também tem um facilitador para funções que chamam funções.

Este é um post introdutório para alguns códigos mais complexos que virão, quase todos resultados das minhas pesquisas de performance de javascript e desenvolvimento de bibliotecas como o jQuery Lazy Load.

Automação de código com CakePHP

Após conhecer os conceitos básicos do CakePHP vamos criar a estrutura base para um sistema para cadastro de produtos e categorias de um e-commerce a partir de um modelo de dados do MySQL. 

Para isso precisaremos de um ambiente com: 

XAMPP ou (PHP + MySQL + PHP)

MySQL Workbench

CakePHP

Banco de Dados

Com o MySQL Workbench, crie uma database chamada ecommerce com 2 tabelas (Products,Categories) e insira informações conforme imagem.

Relacionamento: Products hasOne Category || Categories hasMany Products

 

CakePHP

Primeiramente baixar a versão stable do CakePHP e extrair na raiz do htdocs do seu apache com o nome de ecommerce. 

Para quem usa Windows e instalou o XAMPP, deverá extrair o CakePHP em C:\XAMPP\htdocs\ecommerce.

Dentro do diretório ecommerce abra o arquivo: App/Config/database.php.default e altere as informações para conexão com o banco de dados e aponte para a database ecommerce previamente criada. Feito isso, salve-o como App/Config/database.php.

A config ficará assim: 

public $default = array(
    'datasource' => 'Database/Mysql',
    'persistent' => false,
    'host' => 'localhost',
    'login' => 'user',
    'password' => 'password',
    'database' => 'ecommerce',
    'prefix' => '',
    //'encoding' => 'utf8',
);
 * For MySQL to connect via socket specify the `unix_socket` parameter instead of `host` and `port`
 

Automação CakePHP

Após informar os dados para conexão com o banco, acesse http://localhost/ecommerce e verifique se há algum problema referente à conexão com banco. Havendo, verifique as informações digitadas no arquivo App/Config/database.php e se o serviço de MySQL está rodando. 

Para usuários de windows:

Antes de continuarmos, precisamos adicionar o PHP ao path do sistema operacional. Para isso, siga o procedimento abaixo: 

– Botão direito em 'Meu Computador'

– Clique em Propriedades

– Na aba avançado, clique em variáveis de ambiente

– Na seção "Variáveis de ambiente" encontre a linha Path e clique em editar

– Adicione ao final da linha o caminho para o arquivo php.exe. Se instalou o XAMPP, apenas adicione ao final da linha o trecho: ;C:\XAMPP\php (Com o ponto e vírgula antes!)

– Salve

 

CakePHP, gere uma aplicação a partir da minha database!

– Abra o terminal ou prompt de comando. (Windows + R e digite cmd)

– Navegue até o diretório do ecommerce. (cd C:\XAMPP\htdocs\ecommerce)

– Entre dentro de lib/Cake/Console. (cd lib/Cake/Console)

– Execute: php cake.php bake all

– Neste ponto ele mostrará as tabelas criadas no banco de dados

– Digite o número correspondente a tabela que deseja gerar a aplicação

– Confirme as perguntas posteriores

– Repita o mesmo processo para todas as tabelas. 

 

All done!

http://localhost/ecommerce/categories

Ao acessar, conseguiremos adicionar categorias e produtos! 

 

Dica

Para conhecer mais a fundo como o CakePHP trabalha, visualize os arquivos gerados em app/Model, app/Controller e app/View. O código gerado é limpo e sem gambiarras, extraindo o que o CakePHP tem de melhor. 

Sua estrutura base para começar a trabalhar no desenvolvimento do ecommerce está criada, o resto compete a você.

Utilize a documentação do CakePHP para utilizar ao máximo das funcionalidades do framework. 

 

Links de Referência

Métodos e Exemplos – http://book.cakephp.org/1.3/pt/view/907/Desenvolvendo-com-CakePHP

Validação de campos – http://book.cakephp.org/1.3/pt/view/1143/Valida%C3%A7%C3%A3o-de-dados

+ sobre a Bakery (geração de código) – http://book.cakephp.org/1.3/pt/view/1522/Geração-de-código-com-o-Bake

 

public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'user',
'password' => 'password',
'database' => 'database_name',
'prefix' => '',
//'encoding' => 'utf8',
);

CakePHP – Indrodução ao framework

O que é CakePHP?

CakePHP é um conjunto de scripts e bibliotecas em PHP, OpenSource visando automatizar ações corriqueiras na vida de um programador como CRUD (Create,Read,Update,Delete) de informações usando o modelo MVC.

Como ele trabalha? 

O CakePHP trabalha usando o modelo MVC e com convenção de nomes, ou seja, dentro de uma estrutura MVC cada seção tem uma forma de nomenclatura que veremos a seguir: 

Banco de dados:

Tabelas:

As tabelas devem ser nomeadas no plural seguindo a pluralização da gramática inglesa. Exemplos: users, pages, usuarios, stories. 

Chaves Primárias:

As chaves primárias devem ser nomeadas com "id". Veremos como alterar o id padrão do CakePHP mais adiante.

Chaves Estrangeiras:

As chaves estrangeiras de outras tabelas devem se chamar TabelaSingular_id. Exemplo: Salas possui N Alunos. Na tabela alunos, além da chave primária "id", teremos uma chave estrangeira "sala_id" que referenciará a sala em que o aluno se encontra.

 

MVC:

Model:

Para cada tabela, o CakePHP necessita de uma Model para gerenciar seu conteúdo e esta deve ser nomeada no singular, ou seja,  para uma tabela usuarios a model terá o nome de Usuario.php.

Controller:

Costuma-se ter uma controller para cada model mas podem haver mais. Elas recebem o nome no plural, no caso, UsuariosController.php

View:

As views, interface que o usuário fará interação (forms, inputs de dados) são organizadas dentro de um diretório com nome da Model no plural, no caso Usuarios, e dentro um arquivo com o nome da função dentro da controller, Usuarios/lista.ctp (referenciando a função lista existente dentro da controller Usuarios)

 

URL e fluxo de renderização:

Situação1: O usuário, ainda não cadastrado em nosso sistema, deseja se cadastrar e acessa a url: http://nossodominio.com.br/users/add

Analisando:

Primeira parte, temos o domínio do nosso site http://nossodominio.com.br/, nada de muito especial. Segunda parte, temos users/add, esse nome remete à seguinte estrutura do CakePHP: 

Model: app/Model/User.php

Controller: app/Controller/UsersController.php com chamada para a function add();

View: app/View/Users/add.ctp

ou seja, assim que o usuário acessar essa url o cake seguirá o fluxo: Carregar Model/User.php e Controller/UsersController.php, chamar a function add() e renderizar a view Users/add.ctp.

 

Abaixo a assinatura do método add dentro da UsersController.php

function add(){

### SomeCode ###

}

 

Situação2: O usuário quer editar o post de id=3 já inserido no banco de dados e acessa a url: 

http://nossodominio.com.br/posts/edit/3

Analisando:

Ele fará a mesma coisa da url de usuários com um diferencial; a função edit dentro da PostsController.php espera um parâmetro que é o id do post. Este id é passado na url após o nome da função. 

Abaixo a assinatura do método edit dentro da PostsController.php

 

function edit($id){

### SomeCode ###

}

Conhecendo o básico, veremos como automatizar geração de código através de um modelo de dados SQL usando a Bakery do Cakephp. 

Até breve!

Nova versão do jQuery Lazy Load

Conversando com o Rafael Cavalcante sexta ele me lembrou que eu ainda devia melhorias para aplicar no jQuery Lazy Load Plugin.

Comecei sexta e testei hoje, está tudo no Github.

jQuery Lazy Load Changelog

  • Melhoria de performance
  • Não precisa mais de classe para trabalhar

Changelog detalhado:

Devido as preocupações com performance de javascript mudei um pouco forma como o plugin trabalha.

Com o uso do grep no lugar do each, o jQuery Lazy Load está agora removendo do seu array  todas as imagens que já for carregadas. Elas não são percorridas repetidamente (como acontecia na versão 0.5) e a performance melhorou bastante por conta disso.

Também por conta desta nova forma de trabalhar com o array não é mais necessário o uso de classe (a classe era utilizada para verificar se uma imagem já havia sido carregada). Como preciso manipular menos o DOM também houve ganho de performance por conta disso.

 

Como usar o jQuery Lazy Load

Baixa a última versão do plugin no Github.

Chamando os scripts

Chame o jQuery e o jQuery Lazy Load plugin na sua página.

Preparando as imagens

As imagens que utilizarão o lazy load devem ter a tag data-src com o valor da url da imagem que deverá ser carregada no conteúdo.

Uma dica é chamar o src das imagens para uma imagem transparente e sempre estipular a largura e altura da imagem no próprio HTML, assim sua página vai renderizar mais rápido pois você irá reduzir o reflow do browser.

Outra dica é através de CSS colocar uma imagem de loader como background das imagens que utilizarão o plugin de lazy load, assim se as imagens demorarem para carregar seu usuário terá uma experiência melhor e saberá que algo está acontecendo.

 

Iniciando o Lazy Load

Por último, é só iniciar o plugin com o seletor das imagens que irão utilizar o plugin:

$(function() {
$('.lazy').lazyLoad();
});

 

Pronto, agora seus usuários só carregarão imagens quando necessário.

Javascript: como alterar o intervalo de um timeout?

Estou estudando NodeJS (veja como instalar o NodeJS no Ubuntu) e meu interesse por javascript aumentou com isso – comecei projetos para estudar desenvolvimento de games em javascript.  Nesses estudos percebi que o  setInterval e setTimeout são grandes ferramentas para a criação de scripts complexos, mas que são pouco explorados normalmente. 

Como alterar o interval no Javascript?

Supondo que você instanciou uma função para ser executada 10 segundos depois que o usuário entrar na página (setTimeout). Mas caso o usuário clique no botão Y esta função tem que ter um novo delay, novamente de 10 segundos.

Não encontrei uma maneira de alterar um timeout ou interval em andamento, então a lógica é cancelar o timer que está em funcionamento e setar um novo timer, com o intervalo desejado.

Vamos por partes, cancelando a função já instanciada.

 

Como cancelar um setTimeout em javascript

Nosso código:

var agendamento = setTimeout(function(){
 console.log('ação agendada!');
}, 1000);

/* Cancela o agendamento */
clearTimeout(agendamento);

Simples assim! 

Alterando o intervalo com ação do usuário

var agendamento = setTimeout(function(){
 console.log('ação agendada!');
}, 1000);

$('a.cancela').click(function(){
 clearTimeout(agendamento);
 var agendamento = setTimeout(function(){
  console.log('ação agendada!');
 }, 1000);
});

 

Poderia melhorar o código transformando a criação do agendamento em uma função, mas optei por deixar o mais legível para facilitar o entendimento.

Tem alguma forma diferente de fazer isso? Deixe um comentário!