Paso 4: Abre vínculos externos con una WebView

En este paso, aprenderás lo siguiente:

  • Cómo mostrar contenido web externo dentro de tu app de manera segura y en una zona de pruebas.

Tiempo estimado para completar este paso: 10 minutos
Para obtener una vista previa de lo que completarás en este paso, ve hacia la parte inferior de esta página ↓.

Más información sobre la etiqueta de WebView

Algunas aplicaciones necesitan presentar contenido web externo directamente al usuario, pero mantenerlo dentro de la experiencia de la aplicación. Por ejemplo, un agregador de noticias podría incorporar noticias de sitios externos con todos los formatos, imágenes y comportamiento del sitio original. Para estos y otros usos, las Apps de Chrome tienen una etiqueta HTML personalizada llamada webview.

La app de Tareas pendientes con una WebView

Cómo implementar la etiqueta WebView

Actualiza la app de tareas pendientes para buscar URLs en el texto de elementos pendientes y crea un hipervínculo. Cuando se hace clic en el vínculo, se abre una nueva ventana de la app de Chrome (no una pestaña del navegador) con una vista web que presenta el contenido.

Actualizar permisos

En manifest.json, solicita el permiso webview:

"permissions": [
  "storage",
  "alarms",
  "notifications",
  "webview"
],

Crea una página de incorporación de WebView

Crea un archivo nuevo en la raíz de la carpeta del proyecto y asígnale el nombre webview.html. Este archivo es una página web básica con una etiqueta <webview>:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <webview style="width: 100%; height: 100%;"></webview>
</body>
</html>

Analizar las URLs de los elementos de tareas pendientes

Al final de controller.js, agrega un método nuevo llamado _parseForURLs():

  Controller.prototype._getCurrentPage = function () {
    return document.location.hash.split('/')[1];
  };

  Controller.prototype._parseForURLs = function (text) {
    var re = /(https?:\/\/[^\s"<>,]+)/g;
    return text.replace(re, '<a href="$1" data-src="$1">$1</a>');
  };

  // Export to window
  window.app.Controller = Controller;
})(window);

Cuando se encuentra una cadena que comienza con "http://" o "https://", se crea una etiqueta de anclaje HTML para ajustar la URL.

Busca showAll() en controller.js. Actualiza showAll() para analizar vínculos mediante el método _parseForURLs() que se agregó antes:

/**
 * An event to fire on load. Will get all items and display them in the
 * todo-list
 */
Controller.prototype.showAll = function () {
  this.model.read(function (data) {
    this.$todoList.innerHTML = this.view.show(data);
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
  }.bind(this));
};

Haz lo mismo con showActive() y showCompleted():

/**
 * Renders all active tasks
 */
Controller.prototype.showActive = function () {
  this.model.read({ completed: 0 }, function (data) {
    this.$todoList.innerHTML = this.view.show(data);
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
  }.bind(this));
};

/**
 * Renders all completed tasks
 */
Controller.prototype.showCompleted = function () {
  this.model.read({ completed: 1 }, function (data) {
    this.$todoList.innerHTML = this.view.show(data);
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
  }.bind(this));
};

Por último, agrega _parseForURLs() a editItem():

Controller.prototype.editItem = function (id, label) {
  ...
  var onSaveHandler = function () {
    ...
      // Instead of re-rendering the whole view just update
      // this piece of it
      label.innerHTML = value;
      label.innerHTML = this._parseForURLs(value);
    ...
  }.bind(this);
  ...
}

Aún en editItem(), corrige el código para que use el innerText de la etiqueta en lugar del innerHTML de la etiqueta:

Controller.prototype.editItem = function (id, label) {
  ...
  // Get the innerHTML of the label instead of requesting the data from the
  // Get the innerText of the label instead of requesting the data from the
  // ORM. If this were a real DB this would save a lot of time and would avoid
  // a spinner gif.
  input.value = label.innerHTML;
  input.value = label.innerText;
  ...
}

Abrir una ventana nueva que contiene WebView

Agrega un método _doShowUrl() a controller.js. Este método abre una nueva ventana de la app de Chrome a través de chrome.app.window.create() con webview.html como el código fuente de la ventana:

  Controller.prototype._parseForURLs = function (text) {
    var re = /(https?:\/\/[^\s"<>,]+)/g;
    return text.replace(re, '<a href="$1" data-src="$1">$1</a>');
  };

  Controller.prototype._doShowUrl = function(e) {
    // only applies to elements with data-src attributes
    if (!e.target.hasAttribute('data-src')) {
      return;
    }
    e.preventDefault();
    var url = e.target.getAttribute('data-src');
    chrome.app.window.create(
     'webview.html',
     {hidden: true},   // only show window when webview is configured
     function(appWin) {
       appWin.contentWindow.addEventListener('DOMContentLoaded',
         function(e) {
           // when window is loaded, set webview source
           var webview = appWin.contentWindow.
                document.querySelector('webview');
           webview.src = url;
           // now we can show it:
           appWin.show();
         }
       );
     });
  };

  // Export to window
  window.app.Controller = Controller;
})(window);

En la devolución de llamada chrome.app.window.create(), observa cómo se configura la URL de WebView mediante el atributo de etiqueta src.

Por último, agrega un objeto de escucha de eventos de clic dentro del constructor Controller para llamar a doShowUrl() cuando un usuario haga clic en un vínculo:

function Controller(model, view) {
  ...
  this.router = new Router();
  this.router.init();

  this.$todoList.addEventListener('click', this._doShowUrl);

  window.addEventListener('load', function () {
    this._updateFilterState();
  }.bind(this));
  ...
}

Inicia tu app de tareas pendientes terminada

Has terminado el paso 4. Si vuelves a cargar la app y agregas una tarea pendiente con una URL completa que comienza con http:// o https://, deberías ver algo como lo siguiente:

Más información

Para obtener información más detallada sobre algunas de las APIs presentadas en este paso, consulta lo siguiente:

¿Todo listo para continuar con el siguiente paso? Ir al Paso 5: Agrega imágenes de la Web »