Krok 5. Dodaj obrazy z internetu

W tym kroku poznasz:

  • Jak wczytywać zasoby spoza aplikacji i dodawać je do DOM za pomocą adresów XHR i ObjectURL.

Szacowany czas potrzebny na wykonanie tego kroku: 20 minut.
Aby zobaczyć, co wykonasz w tym kroku, przejdź na sam dół strony ↓.

Jak CSP wpływa na wykorzystanie zasobów zewnętrznych

Platforma Aplikacji Chrome wymusza na aplikacji zachowanie pełnej zgodności z zasadami bezpieczeństwa treści (Content Security Policy, CSP). Nie można bezpośrednio ładować zasobów DOM, takich jak obrazy, czcionki i CSS, spoza pakietu aplikacji Chrome.

Jeśli chcesz wyświetlać w aplikacji obraz zewnętrzny, musisz zażądać go za pomocą XMLHttpRequest, przekształcić go w obiekt Blob i utworzyć obiekt ObjectURL. Element ObjectURL można dodać do DOM, ponieważ odnosi się on do elementu w pamięci w kontekście aplikacji.

Pokaż miniatury elementów do zrobienia

Zmieńmy aplikację tak, aby szukała adresów URL zdjęć w zadaniach do wykonania. Jeśli adres URL wygląda jak obraz (np. kończy się rozszerzeniem .png, .jpg, .svg lub .gif), zastosuj proces omówiony powyżej, aby obok adresu URL była wyświetlana miniatura obrazu.

Aktualizuj uprawnienia

W aplikacji Chrome możesz wywoływać dowolny adres URL (o ile określisz jego domenę w manifeście). Z wyprzedzeniem nie wiesz, jaki adres URL obrazu wpisze użytkownik, dlatego poproś o pozwolenie na przesyłanie żądań do "<all_urls>".

W pliku manifest.json poproś o uprawnienie „”:

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

Tworzenie i usuwanie obiektów ObjectURLs

W pliku controller.js dodaj metodę _createObjectURL(), aby tworzyć obiekty ObjectURL na podstawie obiektu Blob:

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

Obiekty ObjectURL przechowują pamięć, więc jeśli nie potrzebujesz już określonych adresów ObjectURL, anuluj je. Dodaj do pliku controller.js metodę _clearObjectURL(), aby umożliwić:

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

Wyślij żądanie XHR

Dodaj metodę _requestRemoteImageAndAppend(), aby wykonać żądanie XMLHttpRequest z określonym adresem URL obrazu:

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

Podczas wczytywania XHR ta metoda tworzy ObjectURL z odpowiedzi XHR i dodaje element <img> z tym ObjectURL do DOM.

Analizuj adresy URL obrazów w elementach listy zadań

Teraz dodaj metodę _parseForImageURLs(), która będzie wykrywać wszystkie linki, które nie zostały jeszcze przetworzone, i sprawdzać je pod kątem obrazów. W przypadku każdego adresu URL, który wygląda jak obraz, wykonaj _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]);
    }
  }
};

Renderuj miniatury na liście zadań

Teraz zadzwoń do użytkownika _parseForImageURLs() z aplikacji showAll(), showActive() i 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));
};

Zrób to samo z plikiem 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) {
  ...
}

Ogranicz wymiary wyświetlanego obrazu

Na koniec w pliku _bowercomponents/todomvc-common/base.css dodaj regułę CSS, aby ograniczyć rozmiar obrazu:

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

Uruchamianie gotowej aplikacji Todo

Krok 5 został ukończony. Załaduj ponownie aplikację i dodaj zadanie do wykonania z adresem URL do obrazu hostowanego online. Oto przykładowe adresy URL, które możesz użyć: http://goo.gl/nqHMF#.jpg lub http://goo.gl/HPBGR#.png.

Więcej informacji

Szczegółowe informacje o niektórych interfejsach API wprowadzonych w tym kroku znajdziesz tutaj:

Chcesz przejść do następnego kroku? Przejdź do Kroku 6 – Wyeksportuj zadania do wykonania do systemu plików »