Passaggio 5: aggiungi immagini dal web

In questo passaggio, scoprirai:

  • 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'uso delle risorse esterne

La piattaforma per le app di Chrome impone alla tua app di essere pienamente conforme ai criteri di sicurezza del contenuto (CSP). Non puoi caricare direttamente risorse DOM come immagini, caratteri e CSS dall'esterno dell'app Chrome pacchetto.

Se vuoi mostrare un'immagine esterna nella tua app, devi richiederla tramite XMLHttpRequest, trasformarlo in un Blob e creare un ObjectURL. Questo ObjectURL può essere aggiunto al DOM perché fa riferimento a un elemento in memoria nel contesto dell'app.

Mostra le immagini in miniatura delle attività da svolgere

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

Aggiorna autorizzazioni

In un'app di Chrome, puoi effettuare chiamate XMLHttpRequest a qualsiasi URL, purché specifichi il dominio in del file manifest. Dato che non saprai in anticipo quale URL dell'immagine digiterà l'utente, chiedi l'autorizzazione invia richieste a "<all_urls>".

In manifest.json, richiedi il "" autorizzazione:

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

Crea e cancella gli oggetti 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 URL oggetto conservano la memoria, quindi quando non hai più bisogno dell'URL dell'oggetto, devi revocarlo. Aggiungi questo _clearObjectURL() a controller.js per gestirlo:

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 su un determinato URL immagine:

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 delle immagini nelle cose da fare

Ora aggiungi un metodo _parseForImageURLs() che trovi tutti i link non ancora elaborati e li controlli in formato Docker. Per ogni URL simile a 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 nell'elenco delle 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));
};

Fai lo stesso 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 della immagine:

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

Lancia l'app delle cose da fare completata

Hai completato il passaggio 5. Ricarica la tua app e aggiungi una voce di attività con un URL a un'immagine ospitata online. Alcune 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 andare al passaggio successivo? Vai al Passaggio 6: esporta le cose da fare nel file system »