Étape 5: Ajouter des images à partir du Web

Au cours de cette étape, vous allez découvrir:

  • Comment charger des ressources depuis l'extérieur de votre application et les ajouter au DOM via XHR et ObjectURL.

Temps estimé pour terminer cette étape: 20 minutes.
Pour prévisualiser ce que vous allez réaliser au cours de cette étape, accédez au bas de cette page ↓.

Incidence de CSP sur l'utilisation des ressources externes

La plate-forme d'applications Chrome force votre application à être entièrement conforme aux règles de sécurité du contenu (CSP). Vous ne pouvez pas charger directement des ressources DOM telles que des images, des polices et des fichiers CSS en dehors de votre package d'application Chrome.

Si vous souhaitez afficher une image externe dans votre application, vous devez la demander via XMLHttpRequest, la transformer en Blob et créer une URL d'objet (ObjectURL). Ce ObjectURL peut être ajouté au DOM, car il fait référence à un élément en mémoire dans le contexte de l'application.

Afficher les vignettes des tâches

Modifions à présent notre application pour rechercher les URL d'images dans une tâche. Si l'URL ressemble à une image (par exemple, se termine par .png, .jpg, .svg ou .gif), appliquez le processus mentionné ci-dessus pour afficher une vignette d'image à côté de l'URL.

Modifier les autorisations

Dans une application Chrome, vous pouvez effectuer des appels XMLHttpRequest vers n'importe quelle URL, à condition de spécifier son domaine dans le fichier manifeste. Comme vous ne savez pas à l'avance quelle URL d'image l'utilisateur saisira, demandez l'autorisation d'envoyer des requêtes à "<all_urls>".

Dans le fichier manifest.json, demandez l'autorisation "" :

"permissions": ["storage", "alarms", "notifications",
                "webview", "<all_urls>"],

Créer et effacer des ObjectURLs

Dans controller.js, ajoutez une méthode _createObjectURL() pour créer des URL d'objet à partir d'un objet Blob:

Controller.prototype._createObjectURL = function(blob) {
  var objURL = URL.createObjectURL(blob);
  this.objectURLs = this.objectURLs || [];
  this.objectURLs.push(objURL);
  return objURL;
};

Les objets ObjectURL conservent de la mémoire. Par conséquent, lorsque vous n'avez plus besoin de l'ObjectURL, vous devez les révoquer. Ajoutez cette méthode _clearObjectURL() à controller.js pour gérer cela:

Controller.prototype._clearObjectURL = function() {
  if (this.objectURLs) {
    this.objectURLs.forEach(function(objURL) {
      URL.revokeObjectURL(objURL);
    });
    this.objectURLs = null;
  }
};

Envoyer une requête XHR

Ajoutez une méthode _requestRemoteImageAndAppend() pour exécuter une requête XMLHttpRequest sur une URL d'image donnée:

Controller.prototype._requestRemoteImageAndAppend = function(imageUrl, element) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', imageUrl);
  xhr.responseType = 'blob';
  xhr.onload = function() {
    var img = document.createElement('img');
    img.setAttribute('data-src', imageUrl);
    img.className = 'icon';
    var objURL = this._createObjectURL(xhr.response);
    img.setAttribute('src', objURL);
    element.appendChild(img);
  }.bind(this);
  xhr.send();
};

Lors du chargement XHR, cette méthode crée un ObjectURL à partir de la réponse de XHR et ajoute un élément <img> avec ce ObjectURL au DOM.

Analyser les URL des images dans les tâches

Ajoutez maintenant une méthode _parseForImageURLs() qui trouve tous les liens non encore traités et recherche des images. Pour chaque URL qui ressemble à une image, exécutez _requestRemoteImageAndAppend():

Controller.prototype._parseForImageURLs = function () {
  // remove old blobs to avoid memory leak:
  this._clearObjectURL();
  var links = this.$todoList.querySelectorAll('a[data-src]:not(.thumbnail)');
  var re = /\.(png|jpg|jpeg|svg|gif)$/;
  for (var i = 0; i<links.length; i++) {
    var url = links[i].getAttribute('data-src');
    if (re.test(url)) {
      links[i].classList.add('thumbnail');
      this._requestRemoteImageAndAppend(url, links[i]);
    }
  }
};

Afficher les vignettes dans la liste des tâches

Appelez maintenant _parseForImageURLs() depuis showAll(), showActive() et showCompleted():

/**
 * 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._parseForURLs(this.view.show(data));
    this._parseForImageURLs();
  }.bind(this));
};

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

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

Faites la même chose pour editItem() :

Controller.prototype.editItem = function (id, label) {
  ...
  var onSaveHandler = function () {
    ...
    if (value.length && !discarding) {
      ...
      label.innerHTML = this._parseForURLs(value);
      this._parseForImageURLs();
    } else if (value.length === 0) {
  ...
}

Limiter les dimensions de l'image affichée

Enfin, dans _bowercomponents/todomvc-common/base.css, ajoutez une règle CSS pour limiter la taille de l'image:

.thumbnail img[data-src] {
  max-width: 100px;
  max-height: 28px;
}

Lancer votre application Todo terminée

Vous avez terminé l'étape 5 ! Actualisez votre application et ajoutez une tâche avec l'URL d'une image hébergée en ligne. Voici quelques URL que vous pouvez utiliser: http://goo.gl/nqHMF#.jpg ou http://goo.gl/HPBGR#.png.

Pour en savoir plus

Pour plus d'informations sur certaines des API présentées à cette étape, reportez-vous à:

Prêt à passer à l'étape suivante ? Passez à l'Étape 6 : Exporter les tâches dans le système de fichiers »