Neste artigo criaremos um conteúdo interativo com a utilização de boas práticas de desenvolvimento. Estas práticas são recomendadas para projetos maiores, com o intuito de tornar o código sustentável a longo prazo, e consequentemente demandam um conhecimento mais avançado em programação.
O projeto
Nosso conteúdo exibirá uma promoção de sanduíches com botões de reação com seus respectivos contadores. Quando um usuário clicar em algum dos botões, enviaremos para nossa API de registro de interações a data/hora, o Player de origem e a reação selecionada. Dessa forma, uma aplicação cliente poderá consultar estes dados e transformá-los em informações úteis para saber por exemplo quais sanduíches são mais consumidos em determinada região abrangida pelos Players.
Veja abaixo o diagrama de fluxo de uma interação com os botões de reação.
Desenvolvimento
- Crie um novo projeto no 4YouSee Designer;
- Selecione o modelo "Signature Classic Sanduiches";
- Adicione 3 imagens para os nossos botões de reação. Defina para as mesmas os nomes "like", "love" e "dislike";
- Ao lado de cada imagem de botão, adicione um objeto do tipo texto para exibir a contagem de reações;
- Salve e exporte o projeto;
- Iremos adicionar dois repositórios (ver Design the infrastructure persistence layer) para encapsular o acesso e a persistência dos dados. Um para o Player, e outro para as interações:
// /js/interaction/player_repository.js
PlayerRepository = (function(global) {
const API_URL = 'http://127.0.0.1:48567/api/player/status';
function PlayerRepository() {}
var findCurrentPlayer = function() {
return global.fetch(API_URL)
.then(function(response) {
if (response.ok) {
return response.json();
}
throw Error("Status: " + response.status);
});
};
PlayerRepository.prototype.findCurrentPlayer = findCurrentPlayer;
return PlayerRepository;
})(window);// /js/interaction/interaction_repository.js
InteractionRepository = (function(global) {
const API_URL = 'http://api.interactions.com';
function InteractionRepository() {}
var add = function(interaction) {
return global.fetch(API_URL, {
method: 'POST',
body: JSON.stringify(interaction)
}).then(function(response) {
if (response.ok) {
return response.json();
}
throw Error("Status: " + response.status);
});
};
InteractionRepository.prototype.add = add;
return InteractionRepository;
})(window); - Agora adicionaremos um serviço responsável pelas reações, que através do método addReaction irá requisitar os dados do Player e persistir a reação na API.
// /js/interaction/reaction_service.js
ReactionService = (function(global) {
var _playerRepository,
_interactionRepository;
function ReactionService(playerRepository, interactionRepository) {
_playerRepository = playerRepository;
_interactionRepository = interactionRepository;
}
var addReaction = function(reaction) {
_playerRepository.findCurrentPlayer().then(function(data) {
persistReaction(reaction, data.player).then(function() {
dispatchReactionAddedEvent(reaction);
});
});
};
var persistReaction = function(reaction, player) {
return _interactionRepository.add({
payload: reaction,
dateTime: new Date().toISOString(),
type: 'classic_sandwiches_reaction',
player: player
})
};
var dispatchReactionAddedEvent = function(reaction) {
window.dispatchEvent(new CustomEvent('reactionAdded', { detail: reaction }));
};
ReactionService.prototype.addReaction = addReaction;
return ReactionService;
})(window); - Nosso serviço de reações dispara o evento "reactionAdded" utilizado pelo nosso próximo participante, responsável por atualizar o contador de reações, a pseudo classe ReactionCountRenderer. Esta classe recebe em seu construtor um objeto que associa os contadores às respectivas reações.
// /js/interaction/reaction_count_renderer.js
ReactionCountRenderer = (function(global) {
var _counterPerReaction = {};
function ReactionCountRenderer(counterPerReaction) {
_counterPerReaction = counterPerReaction;
addReactionAddedListener();
}
var addReactionAddedListener = function() {
window.addEventListener('reactionAdded', function (e) {
render(e.detail);
});
};
var render = function(reaction) {
var counterElement = document.getElementById(_counterPerReaction[reaction]).getElementsByTagName('p')[0];
var currentCount = parseInt(counterElement.innerHTML);
counterElement.innerHTML = currentCount + 1;
};
return ReactionCountRenderer;
})(window); - Vamos adicionar os handlers do evento click para os botões de reação na pseudo classe DesignerEvents. Alteramos também a mesma para receber em seu construtor o serviço de reações.
// /js/designer_events.js
DesignerEvents = (function (global) {
var _reactionService;
var _eventsPerObject = {
like: {
click: function() {
_reactionService.addReaction('like');
}
},
love: {
click: function() {
_reactionService.addReaction('love');
}
},
dislike: {
click: function() {
_reactionService.addReaction('dislike');
}
}
};
function DesignerEvents(reactionService, eventsPerObject) {
if (eventsPerObject) {
_eventsPerObject = eventsPerObject;
}
addDesignerEventListener();
_reactionService = reactionService;
}
var addDesignerEventListener = function() {
global.addEventListener('designerEvent', function(e) {
handleDesignEvent(e.detail.object, e.detail.event);
});
};
var handleDesignEvent = function(object, event) {
if (_eventsPerObject.hasOwnProperty(object) && _eventsPerObject[object].hasOwnProperty(event)) {
_eventsPerObject[object][event]();
}
};
return DesignerEvents;
})(window); - Na linha 45 do arquivo player_html.js iremos instanciar todos os participantes. Para criar o ReactCountRenderer, obtenha o id dos elementos HTML dos contadores abrindo o projeto em um navegador. Atenção: o arquivo player_html.js é o principal arquivo do conteúdo, cuidado ao alterá-lo!
// /js/player_html.js
reactionService = new ReactionService(new PlayerRepository(), new InteractionRepository()),
designerEvents = new DesignerEvents(reactionService),
reactionCountRenderer = new ReactionCountRenderer({
like: '1543252836692',
love: '1543252876418',
dislike: '1543252894827'
}); - Por fim adicionaremos os novos scripts ao index.html
// index.html
<script type="text/javascript" src="5b8434a78bd7971000000002/js/designer_events.js"></script>
<script type="text/javascript" src="5b8434a78bd7971000000002/js/interaction/interaction_repository.js"></script>
<script type="text/javascript" src="5b8434a78bd7971000000002/js/interaction/player_repository.js"></script>
<script type="text/javascript" src="5b8434a78bd7971000000002/js/interaction/reaction_count_renderer.js"></script>
<script type="text/javascript" src="5b8434a78bd7971000000002/js/interaction/reaction_service.js"></script>
<script type="text/javascript" src="5b8434a78bd7971000000002/js/player_html.js"></script>
O resultado pode ser visto abaixo:
Neste artigo aprendemos a criar conteúdos interativos utilizando separação de conceitos e boas práticas de desenvolvimento.
Abaixo deixamos o vídeo de exemplo e arquivo .zip do template: