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 forma segura y en zona de pruebas

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

Más información sobre la etiqueta de WebView

Algunas aplicaciones deben presentar contenido web externo directamente al usuario, pero mantenerlo dentro de la experiencia de la aplicación. Por ejemplo, un agregador de noticias puede querer incorporar las noticias de sitios externos con todo el formato, las imágenes y el comportamiento del sitio original. Para estos y otros usos, las Apps de Chrome tienen una etiqueta HTML personalizada llamada webview.

La app de Todo usa un WebView

Implementa la etiqueta de WebView

Actualiza la app de Todo para buscar URLs en el texto de la tarea y crear 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 de tu 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>

Analiza las URLs en 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);

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

Busca showAll() en controller.js. Actualiza showAll() para analizar vínculos con el método _parseForURLs() que agregaste anteriormente:

/**
 * 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 para 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;
  ...
}

Abre una ventana nueva que contenga 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 la 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 de chrome.app.window.create(), observa cómo se establece la URL del WebView a través del 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

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

Más información

Para obtener información más detallada sobre algunas de las APIs que se presentan en este paso, consulta los siguientes recursos:

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