Passaggio 5: aggiungi immagini dal web

In questo passaggio, imparerai:

  • Come caricare risorse dall'esterno dell'app e aggiungerle al DOM tramite XHR e ObjectURLs.

Tempo stimato per completare questo passaggio: 20 minuti.
Per visualizzare l'anteprima di ciò che completerai in questo passaggio, vai alla fine di questa pagina ↓.

In che modo CSP influisce sull'utilizzo di risorse esterne

La piattaforma App di Chrome impone la conformità completa della tua app ai Criteri di sicurezza del contenuto (CSP). Non puoi caricare direttamente risorse DOM come immagini, caratteri e CSS dall'esterno del pacchetto di app Chrome.

Se vuoi mostrare un'immagine esterna nella tua app, devi richiederla tramite XMLHttpRequest, trasformarla in un Blob e creare un ObjectURL. Puoi aggiungere questo ObjectURL al DOM perché fa riferimento a un elemento in memoria nel contesto dell'app.

Mostra immagini in miniatura degli elementi attività

Cambiamo l'app in modo che cerchi gli URL immagine in un articolo di promemoria. Se l'URL ha l'aspetto di un'immagine (ad esempio, termina con .png, .jpg, .svg o .gif), applica la procedura descritta in precedenza per mostrare una miniatura dell'immagine accanto all'URL.

Aggiorna autorizzazioni

In un'app di Chrome, puoi effettuare chiamate XMLHttpRequest a qualsiasi URL, a condizione che ne specifichi il dominio nel manifest. Poiché non saprai in anticipo quale URL immagine verrà digitato dall'utente, chiedi l'autorizzazione per effettuare richieste a "<all_urls>".

In manifest.json, richiedi l'autorizzazione "":

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

Crea e cancella gli ObjectURL

In controller.js, aggiungi un metodo _createObjectURL() per creare oggetti ObjectURL da un Blob:

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

Gli oggetti ObjectURL contengono memoria, quindi quando non hai più bisogno di ObjectURL, devi revocarli. Aggiungi questo metodo _clearObjectURL() a controller.js per gestire questa situazione:

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

Effettua una richiesta XHR

Aggiungi un metodo _requestRemoteImageAndAppend() per eseguire una XMLHttpRequest sull'URL di un'immagine specifica:

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();
};

Al caricamento di XHR, questo metodo crea un ObjectURL dalla risposta dell'XHR e aggiunge un elemento <img> con questo ObjectURL al DOM.

Analizza gli URL immagine negli elementi di promemoria

Ora aggiungi un metodo _parseForImageURLs() che trovi tutti i link non ancora elaborati e li controlli per verificare la presenza di immagini. Per ogni URL che sembra un'immagine, esegui _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]);
    }
  }
};

Visualizzare le miniature dell'elenco di cose da fare

Ora chiama _parseForImageURLs() da showAll(), showActive() e 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));
};

Ripeti l'operazione per 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) {
  ...
}

Limita le dimensioni dell'immagine visualizzata

Infine, in _bowercomponents/todomvc-common/base.css, aggiungi una regola CSS per limitare le dimensioni dell'immagine:

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

Avvia l'app Attività completata

Completato il passaggio 5. Ricarica l'app e aggiungi un elemento di attività con un URL a un'immagine ospitata online. Alcuni URL che puoi utilizzare: http://goo.gl/nqHMF#.jpg o http://goo.gl/HPBGR#.png.

Per maggiori informazioni

Per informazioni più dettagliate su alcune delle API introdotte in questo passaggio, fai riferimento a:

Vuoi continuare con il passaggio successivo? Vai al Passaggio 6: esporta le cose da fare nel file system »