En este artículo crearemos contenido interactivo utilizando buenas prácticas de desarrollo. Estas prácticas se recomiendan para proyectos más grandes, con el fin de hacer que el código sea sostenible a largo plazo y, en consecuencia, requieren un conocimiento más avanzado en programación.
El proyecto
Nuestro contenido incluirá una promoción sandwich con botones de reacción con sus respectivos contadores. Cuando un usuario hace clic en cualquiera de los botones, enviaremos la fecha / hora, el reproductor de origen y la reacción seleccionada a nuestra API de registro de interacción. De esta forma, una aplicación cliente podrá consultar estos datos y convertirlos en información útil para saber, por ejemplo, qué sándwiches se consumen más en una región determinada cubierta por los jugadores.
Vea el diagrama de flujo de una interacción con los botones de reacción a continuación.
Desarrollo
1. Cree un nuevo proyecto en 4YouSee Designer;
2. Seleccione el modelo "Signature Classic Sandwiches";
3. Agregue 3 imágenes a los botones de reacción. Defina los nombres "me gusta", "amor" y "disgusto" para ellos;
4. Junto a cada imagen de botón, agregue un objeto de texto para mostrar el recuento de reacción;
5. Guardar y exportar el proyecto;
6. Agregaremos dos repositorios (consulte Diseño de la capa de persistencia de infraestructura) para encapsular el acceso a los datos y la persistencia. Uno para el jugador y otro para las interacciones:
// /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);
7. Ahora agregaremos un servicio responsable de las reacciones, que a través del método addReaction solicitará los datos del reproductor y persistirá la reacción en la 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);
8. Nuestro servicio de reacción desencadena el evento "reactionAdded" utilizado por nuestro próximo participante, responsable de actualizar el contador de reacción, la pseudo clase ReactionCountRenderer. Esta clase recibe en su constructor un objeto que asocia los contadores con las reacciones respectivas.
// /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);
9. Agreguemos los controladores del evento click a los botones de reacción en la pseudo clase DesignerEvents. También lo cambiamos para recibir el servicio de reacciones de su fabricante.
// /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);
10. En la línea 45 del archivo player_html.js, crearemos una instancia de todos los participantes. Para crear el ReactCountRenderer, obtenga la identificación de los elementos HTML de los contadores abriendo el proyecto en un navegador. Atención: el archivo player_html.js es el archivo principal del contenido, ¡tenga cuidado al cambiarlo!
// /js/player_html.js
reactionService = new ReactionService(new PlayerRepository(), new InteractionRepository()),
designerEvents = new DesignerEvents(reactionService),
reactionCountRenderer = new ReactionCountRenderer({
like: '1543252836692',
love: '1543252876418',
dislike: '1543252894827'
});
11. Finalmente agregaremos los nuevos scripts al 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>
En este artículo, aprendemos a crear contenido interactivo usando la separación de conceptos y buenas prácticas de desarrollo.