Hoy vamos a ver cómo crear una sencilla directiva en AngularJS. Ésta consiste en la creación de un atributo que, aprovechando la API de Google Translate, leerá el texto de la etiqueta. Además, podremos habilitar o deshabilitar la funcionalidad de lectura.

Lo primero como siempre será crear un módulo. Yo voy a ser original y llamarlo ttsApp.

  var ttsApp = angular.module('ttsApp', []);

Lo siguiente será la declaración de directiva. La idea es declararla como atributo, así podemos incluirla en las etiquetas que queramos, bien sea span, div, li o botón (por ejemplo: Bienvenido, Walter leería en voz alta el contenido de dicho span). Así, el esqueleto de nuestra directiva será el siguiente:

 ttsApp.directive('tts', function(){
  return {
   restrict: 'A', //Attribute
   link: function(scope, element, attrs){
   }
  }
 });

Ahora va el interior de la función link, que es la que realmente habilita el funcionamiento de la directiva. Si os fijáis, uno de los tres atributos recibidos es el tag con el que trabajamos, y otro es el conjunto de atributos del mismo.

Lo que vamos a hacer es que el audio se reproduzca cuando pasamos el ratón por encima.

  element.bind('mouseenter', function(){
     if(eval(attrs.tts) && !isPlaying){
      playAudio(element.text());
    }
  });

Sencillo, ¿no? He metido un eval porque el atributo tts me lo representa como “true” y “false” en string, y necesito los valores booleanos.

El siguiente ejemplo muestra el funcionamiento completo, y asocia la lectura o no del texto al modelo ttsEnabled, gestionado por un checkbox. Aquí ya vienen definidas las funciones playAudio y stopAudio. También, vemos que se propagan eventos cuando pasamos de un ítem a otro y hay un mejor control del audio. De esta manera sólo se lee el texto del último ítem sobre el que hemos pasado.

Lo he dejado también en este fiddle para poder probarlo online. A mi en casa JSFiddle me está dando problemas con la API de Google y no me lo lee si no está cacheado. Sin embargo, si el código lo lanzo en local sí que lo lee.

<!DOCTYPE html>
<html>
<head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 <title>Translate TTS demo - jsFiddle demo by alexsuch</title>
 <script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js'></script>
 <script type='text/javascript'>

   var ttsApp = angular.module('ttsApp', []);

   ttsApp.directive('tts', function(){
    return {
     restrict: 'A',
     link: function(scope, element, attrs){
      var audio = null;
      var isPlaying = false;

      var playAudio = function(text, onFinish){
       console.log('play audio')
       audio = new Audio('http://translate.google.com/translate_tts?tl=es&q=' + encodeURIComponent(text));
       audio.play();
       audio.addEventListener('ended', onFinish);
       audio.addEventListener('error', function(error){ console.log('error', error); onFinish(); });
     };

     var stopAudio = function(){
       if(audio)
        audio.pause();
    }

    scope.$on('audioPlaying', function(){
     stopAudio();
     isPlaying = false;
   });

  element.bind('mouseenter', function(){
     if(eval(attrs.tts) && !isPlaying){
      isPlaying = true;
      scope.$broadcast('audioPlaying', []);
      playAudio(element.text(), function(){
       isPlaying = false;
     });
    }
  });

  }
}
});

 </script>


</head>
<body ng-app="ttsApp">
 <div>
  <ul>
   <li tts="{{ttsEnabled}}">Página principal</li>
   <li tts="{{ttsEnabled}}">Búsqueda en google</li>
   <li tts="{{ttsEnabled}}">Registro de usuarios</li>
 </ul>
 <label><input type="checkbox" ng-model="ttsEnabled" /> Habilitar voz</label>
</div>
</body>
</html>
Anuncios