Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4743)

Unified Diff: chrome/common/extensions/docs/templates/articles/app_codelab_images.html

Issue 645693006: Updated Chrome Apps codelab (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/docs/templates/articles/app_codelab_images.html
diff --git a/chrome/common/extensions/docs/templates/articles/app_codelab_images.html b/chrome/common/extensions/docs/templates/articles/app_codelab_images.html
new file mode 100644
index 0000000000000000000000000000000000000000..df161d8cb4bb093d68703c9b54c1bd64fcbfeb60
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/articles/app_codelab_images.html
@@ -0,0 +1,225 @@
+<h1 id="add-images">
+ <span class="h1-step">Step 5:</span>
+ Add Images From the Web
+</h1>
+
+<p class="note">
+ <strong>Want to start fresh from here?</strong>
+ Find the previous step's code in the <a href="https://github.com/mangini/io13-codelab/archive/master.zip">reference code zip</a> under <strong><em>cheat_code > solution_for_step4</strong></em>.
+</p>
+
+<p>In this step, you will learn:</p>
+
+<ul>
+ <li>How to load resources from outside your app and add them to the DOM through XHR and ObjectURLs.</li>
+</ul>
+
+<p>
+ <em>Estimated time to complete this step: 20 minutes.</em>
+ <br>
+ To preview what you will complete in this step, <a href="#launch">jump down to the bottom of this page &#8595;</a>.
+</p>
+
+<h2 id="csp-compliance">Learn how CSP affects the use of external web resources</h2>
+
+<p>The Chrome Apps platform forces your app to be fully compliant with Content
+Security Policies (CSP). This includes not being able to directly load DOM
+resources like images, fonts, and CSS from outside of your packaged app.</p>
+
+<p>If you want to show an external image in your app, you need to request it via <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a>,
+transform it into a <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>, and create an <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL">ObjectURL</a>. This ObjectURL can then be
+added to the DOM because it refers to an in-memory item in the context of the
+app.</p>
+
+<h2 id="show-images">Show thumbnail images for todo items</h2>
+
+<p>Let's change our app to look for image URLs in a todo item. If the URL
+looks like an image (e.g. ends with .png, .jpg, .svg, or .gif), we will apply the
+process mentioned above in order to show an image thumbnail next to the URL.</p>
+
+<h3 id="update-permissions">Update permissions</h3>
+
+<p>In a Chrome App you can make XMLHttpRequest calls to any URL as long as you
+whitelist its domain in the manifest. Since we won't know
+beforehand what image URL the user will type,
+we will ask permission to make requests to <code>"&lt;all_urls&gt;"</code>.</p>
+
+<p>In <strong><em>manifest.json</em></strong>, request the "&lt;all_urls&gt;" permission:</p>
+
+<pre data-filename="manifest.json">
+"permissions": ["storage", "alarms", "notifications",
+ "webview"<b>, "&lt;all_urls&gt;"</b>],
+</pre>
+
+<h3 id="object-urls">Create and clear ObjectURLs</h3>
+
+In <strong><em>controller.js</em></strong>, add a <code>_createObjectURL()</code> method to create ObjectURLs from a Blob:
+
+<pre data-filename="controller.js">
+Controller.prototype._createObjectURL = function(blob) {
+ var objURL = URL.createObjectURL(blob);
+ this.objectURLs = this.objectURLs || [];
+ this.objectURLs.push(objURL);
+ return objURL;
+};
+</pre>
+
+<p>ObjectURLs hold memory so, when you no longer need the ObjectURL, you
+should revoke them. Add this
+<code>_clearObjectURL()</code> method to <em>controller.js</em> to handle that:</p>
+
+<pre data-filename="controller.js">
+Controller.prototype._clearObjectURL = function() {
+ if (this.objectURLs) {
+ this.objectURLs.forEach(function(objURL) {
+ URL.revokeObjectURL(objURL);
+ });
+ this.objectURLs = null;
+ }
+};
+</pre>
+
+<h3 id="xhr">Make a XHR request</h3>
+
+<p>Add a <code>_requestRemoteImageAndAppend()</code> method to execute a XMLHttpRequest
+on a given image URL:</p>
+
+<pre data-filename="controller.js">
+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();
+};
+</pre>
+
+<p>On XHR load, this method will create an ObjectURL from the XHR's response,
+and add an <code>&lt;img&gt;</code> element with this ObjectURL to the DOM.</p>
+
+<h3 id="parse-urls">Parse for image URLs in todo items</h3>
+
+<p>Now add a <code>_parseForImageURLs()</code> method that finds all links not yet processed and checks them
+for images. For each URL that looks like an image, execute <code>_requestRemoteImageAndAppend()</code>:
+
+<pre data-filename="controller.js">
+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&lt;links.length; i++) {
+ var url = links[i].getAttribute('data-src');
+ if (re.test(url)) {
+ links[i].classList.add('thumbnail');
+ this._requestRemoteImageAndAppend(url, links[i]);
+ }
+ }
+};
+</pre>
+
+<h3 id="render-thumbnails">Render thumbnails in the todo list</h3>
+
+<p>Now call <code>_parseForImageURLs()</code> from <code>showAll()</code>, <code>showActive()</code>, and
+<code>showCompleted()</code>:</p>
+
+<pre data-filename="controller.js">
+/**
+ * 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));
+ <b>this._parseForImageURLs();</b>
+ }.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));
+ <b>this._parseForImageURLs();</b>
+ }.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));
+ <b>this._parseForImageURLs();</b>
+ }.bind(this));
+};
+</pre>
+
+<p>Do the same for <code>editItem()</code>:</p>
+
+<pre data-filename="controller.js">
+Controller.prototype.editItem = function (id, label) {
+ ...
+ var onSaveHandler = function () {
+ ...
+ if (value.length &amp;&amp; !discarding) {
+ ...
+ label.innerHTML = this._parseForURLs(value);
+ <b>this._parseForImageURLs();</b>
+ } else if (value.length === 0) {
+ ...
+}
+</pre>
+
+<h3 id="css">Constrain the displayed image dimensions</h3>
+
+<p>Finally, in <strong></em>bower_components/todomvc-common/base.css</strong></em>, add a CSS rule to limit
+ the size of the image:</p>
+
+<pre data-filename="base.css">
+.thumbnail img[data-src] {
+ max-width: 100px;
+ max-height: 28px;
+}
+</pre>
+
+<h2 id="launch">Launch your finished Todo app</h2>
+
+<p>You are done Step 5! Reload your app and add a todo item with a URL
+to an image hosted online. Some URLs you could use: <strong>http://goo.gl/nqHMF#.jpg</strong> or <strong>http://goo.gl/HPBGR#.png</strong>.</p>
+
+<p>The result should be something like this:</p>
+
+<figure>
+ <img src="{{static}}/images/app_codelab/step5-completed.gif" alt="The Todo app with image thumbnails"/>
+</figure>
+
+<p class="note"><strong>Tip</strong>: For real-world situations, when you need to control
+offline cache and dozens of simultaneous resource downloads, we have created
+<a href="https://github.com/GoogleChrome/apps-resource-loader#readme">a helper library</a>
+to handle some common use cases.</p>
+
+<h2 id="recap">Recap APIs referenced in this step</h2>
+
+<p>For more detailed information about some of the APIs introduced in this step, refer to:</p>
+
+<ul>
+ <li>
+ <a href="/apps/contentSecurityPolicy" title="Read 'Content Security Policy' in the Chrome developer docs">Content Security Policy</a>
+ <a href="#csp-compliance" class="anchor-link-icon" title="This feature mentioned in 'Learn how CSP affects the use of external web resources'">&#8593;</a>
+ </li>
+ <li>
+ <a href="/apps/declare_permissions" title="Read 'Declare Permissions' in the Chrome developer docs">Declare Permissions</a>
+ <a href="#update-permissions" class="anchor-link-icon" title="This feature mentioned in 'Update permissions'">&#8593;</a>
+ </li>
+</ul>
+
+<p>Ready to continue onto the next step? Go to <a href="app_codelab_filesystem.html">Step 6 - Export todos to the filesystem &raquo;</a></p>

Powered by Google App Engine
This is Rietveld 408576698