Nesta etapa, você vai aprender:
- Como carregar recursos de fora do app e adicioná-los ao DOM usando XHR e ObjectURLs.
Tempo estimado para concluir esta etapa: 20 minutos.
Para visualizar o que você concluirá nesta etapa, vá para a parte inferior desta página ↓.
Como o CSP afeta o uso de recursos externos
A plataforma de Aplicativos do Google Chrome força seu aplicativo a estar em total conformidade com as Políticas de Segurança de Conteúdo (CSP). Não é possível carregar recursos DOM diretamente, como imagens, fontes e CSS de fora do app do Chrome .
Se você quiser mostrar uma imagem externa no app, é necessário solicitá-la com XMLHttpRequest,
transformá-lo em um Blob e criar um ObjectURL. Esse ObjectURL
pode ser adicionado ao
DOM, porque se refere a um item na memória no contexto do app.
Mostrar imagens em miniatura para itens de tarefas
Vamos mudar nosso app para procurar URLs de imagem em um item de tarefas. Se o URL se parecer com uma imagem (por exemplo, termine com .png, .jpg, .svg ou .gif), aplique o processo mencionado acima para exibir uma miniatura de imagem ao lado do URL.
Atualizar permissões
Em um aplicativo do Google Chrome, é possível fazer chamadas XMLHttpRequest para qualquer URL, contanto que você especifique o domínio em
no manifesto. Como você não sabe com antecedência qual URL de imagem o usuário digitará, peça permissão para
fazer solicitações para "<all_urls>"
.
No manifest.json, solicite o "
"permissions": ["storage", "alarms", "notifications",
"webview", "<all_urls>"],
Criar e limpar ObjectURLs
No controller.js (link em inglês), adicione um método _createObjectURL()
para criar ObjectURLs de um blob:
Controller.prototype._createObjectURL = function(blob) {
var objURL = URL.createObjectURL(blob);
this.objectURLs = this.objectURLs || [];
this.objectURLs.push(objURL);
return objURL;
};
Os ObjectURLs mantêm memória, portanto, quando você não precisar mais do ObjectURL, revogue-os. Adicionar
Método _clearObjectURL()
para controller.js a fim de processar isso:
Controller.prototype._clearObjectURL = function() {
if (this.objectURLs) {
this.objectURLs.forEach(function(objURL) {
URL.revokeObjectURL(objURL);
});
this.objectURLs = null;
}
};
Fazer uma solicitação XHR
Adicione um método _requestRemoteImageAndAppend()
para executar um XMLHttpRequest em um determinado URL de imagem:
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();
};
No carregamento XHR, esse método cria um ObjectURL
a partir da resposta do XHR e adiciona um elemento <img>
com este ObjectURL
ao DOM.
Analisar URLs de imagens em itens de tarefas
Agora, adicione um método _parseForImageURLs()
que encontre todos os links ainda não processados e verifique se eles foram encontrados
de imagens de contêiner. Execute _requestRemoteImageAndAppend()
para cada URL semelhante a uma imagem:
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]);
}
}
};
Renderizar miniaturas na lista de tarefas
Agora, chame _parseForImageURLs()
de 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));
};
Faça o mesmo para 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) {
...
}
Restringir as dimensões da imagem exibida
Por fim, em _bowercomponents/todomvc-common/base.css, adicione uma regra CSS para limitar o tamanho do imagem:
.thumbnail img[data-src] {
max-width: 100px;
max-height: 28px;
}
Iniciar o app Todo concluído
Você concluiu a Etapa 5! Atualize o app e adicione um item de tarefas com um URL para uma imagem hospedada on-line. Algumas URLs que podem ser usados: http://goo.gl/nqHMF#.jpg ou http://goo.gl/HPBGR#.png.
Mais informações
Para informações mais detalhadas sobre algumas das APIs introduzidas nesta etapa, consulte:
Tudo pronto para passar para a próxima etapa? Vá para a Etapa 6: exportar tarefas para o sistema de arquivos »