Index: src/site/codelabs/darrrt/index.markdown |
diff --git a/src/site/codelabs/darrrt/index.markdown b/src/site/codelabs/darrrt/index.markdown |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e40df989a949975764252027dab12d54a6104ece |
--- /dev/null |
+++ b/src/site/codelabs/darrrt/index.markdown |
@@ -0,0 +1,1784 @@ |
+--- |
+layout: default |
+title: "Try Dart" |
+description: "Write some Dart code. Learn some stuff." |
+has-permalinks: true |
+tutorial: |
+ id: trydart |
+js: |
+- url: /js/os-switcher.js |
+ defer: true |
+- url: /js/editor-downloads-analytics.js |
+ defer: true |
+- url: /js/editor-version.js |
+ defer: true |
+header: |
+ css: ["/codelabs/darrrt/darrrt.css"] |
+--- |
+ |
+# {{ page.title }} |
+ |
+## Got an hour? Write a Dart app. |
+ |
+In this code lab, |
+you build a pirate badge generator from a skeleton app. |
+The sample app provides a brief look at some Dart language and library features. |
+This code lab assumes that you have some programming experience. |
+ |
+<strong>Build this app!</strong> |
+ |
+<iframe class="running-app-frame" |
+ style="height:220px;width:530px;" |
+ src="examples/6-piratebadge_json/piratebadge.html"> |
+</iframe> |
+ |
+<hr> |
+ |
+## The Map |
+ |
+* [Step 0: Set up](#set-up) |
+* [Step 1: Run the skeleton app](#step-one) |
+* [Step 2: Add an input field](#step-two) |
+* [Step 3: Add a button](#step-three) |
+* [Step 4: Create a class](#step-four) |
+* [Step 5: Save to local storage](#step-five) |
+* [Step 6: Read names from JSON file using HttpRequest](#step-six) |
+* [Step 7: Go forth and learn more about Dart](#step-seven) |
+ |
+ |
+<hr> |
+ |
+## Step 0: Set up {#set-up} |
+ |
+In this step, you download Dart and get the sample code. |
+ |
+ |
+#### <i class="icon-anchor"> </i> Get Dart. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+If you haven't already done so, |
+get the Dart download. |
+Unzip the ZIP file, which creates a directory called `dart`. |
+ |
+{% include downloads/_dart-editor.html %} |
+ |
+<p markdown="1"> |
+ The Dart tools |
+ work in recent versions of |
+ {% include os-choices.html %} |
+</p> |
+</div> |
+ |
+#### <i class="icon-anchor"> </i> Start the editor. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Go to the `dart` directory and double-click **DartEditor**. |
+ |
+**Got questions? Having trouble?** Go to the |
+[Troubleshooting Dart Editor](/tools/editor/troubleshoot.html) page. |
+ |
+</div> |
+ |
+#### <i class="icon-anchor"> </i> Get the sample code. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+<a href="https://github.com/dart-lang/one-hour-codelab/archive/master.zip">Download</a> |
+the sample code. |
+Unzip the ZIP file, |
+which creates a directory called `one-hour-codelab-master`. |
+</div> |
+ |
+#### <i class="icon-anchor"> </i> Open the one-hour-codelab-master sample. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+In Dart Editor, |
+use **File > Open Existing Folder...** |
+to open the `one-hour-codelab-master` directory. |
+</div> |
+ |
+<div class="row"> <div class="span7" markdown="1"> |
+ |
+ |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+<i class="icon-key"> </i> <strong> Key Information </strong> |
+ |
+* The `packages` directory, as well as the `pubspec.yaml` and `pubspec.lock` files are |
+related to package dependencies. |
+This project has all the dependencies set up for you. |
+Dart Editor automatically installs the necessary packages. |
+ |
+* Several numbered directories contain the completed code for each step. |
+`1-blankbadge` contains the skeletal version of the app that you begin with. |
+`6-piratebadge_json` contains the final version of the app. |
+ |
+* The `piratebadge.css` file |
+provides the CSS styles for all steps of the app. |
+You don't change this file during this code lab. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+<hr> |
+ |
+##Step 1: Run the skeleton app {#step-one} |
+ |
+In this step, you open the source files, |
+familiarize yourself with the Dart and HTML code, |
+and run the app. |
+ |
+#### <i class="icon-anchor"> </i> Expand the 1-blankbadge directory. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+In Dart Editor, expand the `1-blankbadge` directory |
+by clicking the little arrow |
+ to the left of its name. |
+The directory contains two files, `piratebadge.html` and `piratebadge.dart`. |
+</div> |
+ |
+#### <i class="icon-anchor"> </i> Open the files. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Open both files, `piratebadge.html` and `piratebadge.dart`, |
+by double-clicking each filename in Dart Editor. |
+</div> |
+ |
+#### <i class="icon-anchor"> </i> Review the code. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Get familiar with the HTML and the Dart code for the skeleton version of the app. |
+</div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+##### piratebadge.html |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+{% prettify html%} |
+<html> |
+ <head> |
+ <meta charset="utf-8"> |
+ <title>Pirate badge</title> |
+ <link rel="stylesheet" href="../piratebadge.css"> |
+ </head> |
+ <body> |
+ <h1>Pirate badge</h1> |
+ |
+ [[highlight]]<div class="widgets">[[/highlight]] |
+ [[highlight]]TO DO: Put the UI widgets here.[[/highlight]] |
+ [[highlight]]</div>[[/highlight]] |
+ <div class="badge"> |
+ <div class="greeting"> |
+ Arrr! Me name is |
+ </div> |
+ <div class="name"> |
+ [[highlight]]<span id="badgeName"> </span>[[/highlight]] |
+ </div> |
+ </div> |
+ |
+ [[highlight]]<script type="application/dart" src="piratebadge.dart"></script>[[/highlight]] |
+ [[highlight]]<script src="packages/browser/dart.js"></script>[[/highlight]] |
+ </body> |
+</html> |
+{% endprettify %} |
+ |
+</div> |
+<div class="trydart-filename">piratebadge.html</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+<i class="icon-key"> </i> <strong> Key Information </strong> |
+ |
+* During this code lab, |
+all the changes you make to `piratebadge.html` are within |
+the <div> element identified with the class `widgets`. |
+ |
+* In later steps, |
+the <span> element with the ID `badgeName` |
+is programmatically updated by the Dart code |
+based on user input. |
+ |
+* The `piratebadge.dart` script provides the main program for the app. |
+ |
+* The `packages/browser/dart.js` script is a bootstrap script |
+that takes care of turning on the Dart VM, |
+as well as compatibility with non-Dart browsers. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+##### piratebadge.dart |
+</div> |
+ |
+<div class="row"> <div class="span7" markdown="1"> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+{% prettify dart %} |
+[[highlight]]void main() { |
+ // Your app starts here. |
+} |
+[[/highlight]] |
+{% endprettify %} |
+</div> |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* This file is the main script for the app. |
+It is referenced by a <script> tag in the `piratebadge.html` file. |
+ |
+* The `main()` function is a top-level function. |
+ Dart calls this function when your app starts. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+</div> </div> |
+ |
+#### <i class="icon-anchor"> </i> Run the app. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+To run the app in Dart Editor, select `piratebadge.html` |
+and click the Run button |
+<img src="images/run.png" width="16" height="16" |
+ alt="Run button">. |
+ |
+ |
+ |
+You should see a TO DO comment on the left |
+and a red and white name badge on the right. |
+</div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+<iframe class="running-app-frame" |
+ style="height:220px;width:530px;" |
+ src="examples/1-blankbadge/piratebadge.html"> |
+</iframe> |
+</div> |
+ |
+<hr> |
+ |
+##Step 2: Add an input field {#step-two} |
+ |
+<div class="trydart-note" markdown="1"> |
+<strong>Note:</strong> Throughout this code lab, |
+continue to edit the files in `1-blankbadge`. |
+You can use the files in the other directories to compare to your code |
+or to recover if you get off track. |
+</div> |
+ |
+In this step, you add an input field to the app. |
+As the user types into the text field, |
+the Dart code updates the badge from the value of the text field. |
+ |
+#### <i class="icon-anchor"> </i> Edit piratebadge.html. |
+ |
+<div class="row"> <div class="span7" markdown="1"> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Add the <input> tag to the HTML code |
+within the `widgets` <div>. |
+ |
+{% prettify html %} |
+... |
+<div class="widgets"> |
+[[highlight]] <div> |
+ <input type="text" id="inputName" maxlength="15"> |
+ </div>[[/highlight]] |
+</div> |
+... |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.html</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+<i class="icon-key"> </i> <strong> Key Information </strong> |
+ |
+* The ID for the input element is `inputName`. |
+Dart uses CSS selectors, like this ID, |
+to get elements from the DOM. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+#### <i class="icon-anchor"> </i> Edit piratebadge.dart. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Import the `dart:html` |
+library at the top of the file |
+(below the copyright). |
+ |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+{% prettify dart %} |
+[[highlight]]import 'dart:html';[[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* This imports all classes and other resources from dart:html, |
+which provides HTML elements and access to the DOM. |
+ |
+* Dart Editor helpfully warns you that the import is unused. |
+Don't worry about it. You'll fix it in the next step. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Register a function to handle input events on the input field. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+{% prettify dart %} |
+void main() { |
+ [[highlight]]querySelector('#inputName').onInput.listen(updateBadge);[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* The `querySelector()` function, defined in |
+dart:html, gets an element from the DOM. |
+Here, the code uses the ID `#inputName` |
+to specify the input field. |
+ |
+* `onInput` registers an event handler for input events. |
+ |
+* An input event occurs when the user presses a key. |
+ |
+* You can use either single or double quotes to create a string. |
+ |
+* Dart Editor warns you that the function doesn't exist. |
+Let's fix that now. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Implement the event handler as a top-level function. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+{% prettify dart %} |
+... |
+ |
+[[highlight]]void updateBadge(Event e) { |
+ querySelector('#badgeName').text = (e.target as InputElement).value; |
+}[[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* This function sets the text of the `badgeName` element from the value of the input field. |
+ |
+* You can tell that `updateBadge()` is an event handler because it takes an |
+`Event` object. |
+ |
+* The element that generated the event, the input field, is `e.target`. |
+ |
+* The `as` keyword typecasts `e.target` to an |
+`InputElement`. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+#### <i class="icon-anchor"> </i> Run the app. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Save your files with **File > Save All**. |
+ |
+Use the Run button |
+<img src="images/run.png" width="16" height="16" |
+ alt="Run button"> |
+in Dart Editor to run the app. |
+ |
+Compare your app to the one running below. |
+ |
+Type in the input field. |
+ |
+<iframe class="running-app-frame" |
+ style="height:220px;width:530px;" |
+ src="examples/2-inputnamebadge/piratebadge.html"> |
+</iframe> |
+ |
+##### Problems? |
+ |
+Check your code against the files in `2-inputbadge`. |
+ |
+* [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/web/2-inputnamebadge/piratebadge.html) |
+ |
+* [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/web/2-inputnamebadge/piratebadge.dart) |
+</div> |
+ |
+ |
+<hr> |
+ |
+##Step 3: Add a button {#step-three} |
+ |
+In this step, you add a button to the app. |
+The button is enabled when the text field contains no text. |
+When the user clicks the button, |
+the app puts the name `Anne Bonney` on the badge. |
+ |
+#### <i class="icon-anchor"> </i> Edit piratebadge.html. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Add the <button> tag below the input field. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify html %} |
+... |
+<div class="widgets"> |
+ <div> |
+ <input type="text" id="inputName" maxlength="15"> |
+ </div> |
+[[highlight]] <div> |
+ <button id="generateButton">Aye! Gimme a name!</button> |
+ </div>[[/highlight]] |
+</div> |
+... |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.html</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+<i class="icon-key"> </i> <strong> Key Information </strong> |
+ |
+* The button has the ID `generateButton` so |
+the Dart code can get the element. |
+ |
+</div> </div> |
+ |
+#### <i class="icon-anchor"> </i> Edit piragebadge.dart. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Below the import, declare a top-level variable to hold the `ButtonElement`. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+import 'dart:html'; |
+ |
+[[highlight]]ButtonElement genButton;[[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Top-level variables are names at the library level. |
+ |
+* ButtonElement is one of many different kinds of DOM elements |
+provided by the dart:html library. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Wire up the button with an event handler. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void main() { |
+ querySelector('#inputName').onInput.listen(updateBadge); |
+ [[highlight]]genButton = querySelector('#generateButton'); |
+ genButton.onClick.listen(generateBadge);[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* `onClick` registers a mouse click handler. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Add a top-level function that changes the name on the badge. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+... |
+ |
+[[highlight]]void setBadgeName(String newName) { |
+ querySelector('#badgeName').text = newName; |
+} [[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* The function updates the HTML page with a new name. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Implement the click handler for the button. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+... |
+ |
+[[highlight]]void generateBadge(Event e) { |
+ setBadgeName('Anne Bonney'); |
+}[[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* This function sets the badge name to `Anne Bonney`. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+Modify `updateBadge()` to call `setBadgeName()`. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void updateBadge(Event e) { |
+[[highlight]] String inputName = [[/highlight]](e.target as InputElement).value; |
+[[highlight]] setBadgeName(inputName);[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Assign the input field's value to a local string. |
+ |
+</div></div> |
+ |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Now add code to `updateBadge()` to enable and disable the button as needed. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void updateBadge(Event e) { |
+ String inputName = (e.target as InputElement).value; |
+ setBadgeName(inputName); |
+[[highlight]] if (inputName.trim().isEmpty) { |
+ genButton..disabled = false |
+ ..text = 'Aye! Gimme a name!'; |
+ } else { |
+ genButton..disabled = true |
+ ..text = 'Arrr! Write yer name!'; |
+ }[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* The `String` class has useful functions and properties for dealing with strings, |
+such as `trim()` and `isEmpty`. |
+ |
+* String comes from the `dart:core` library, |
+which is automatically imported into every Dart program. |
+ |
+* The cascade operator (`..`) allows you to perform multiple |
+operations on the members of a single object. |
+ |
+* Dart has common programming language constructs like `if`-`else`. |
+ |
+</div></div> |
+ |
+#### <i class="icon-anchor"> </i> Run the app. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Save your files with **File > Save All**. |
+ |
+Use the Run button |
+<img src="images/run.png" width="16" height="16" |
+ alt="Run button"> |
+in Dart Editor to run the app. |
+ |
+Compare your app to the one running below. |
+ |
+Type in the input field. |
+Remove the text from the input field. |
+Click the button. |
+ |
+<iframe class="running-app-frame" |
+ style="height:220px;width:530px;" |
+ src="examples/3-buttonbadge/piratebadge.html"> |
+</iframe> |
+ |
+ |
+##### Problems? |
+ |
+Check your code against the files in `3-buttonbadge`. |
+ |
+* [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/web/3-buttonbadge/piratebadge.html) |
+ |
+* [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/web/3-buttonbadge/piratebadge.dart) |
+ |
+</div> |
+ |
+ |
+<hr> |
+ |
+##Step 4: Create a PirateName class {#step-four} |
+ |
+In this step, you change only the Dart code. |
+You create a class to represent a pirate name. |
+When created, an instance of this class |
+randomly selects a name and appellation from a list, |
+or optionally you can provide a name |
+and an appellation to the constructor. |
+ |
+#### <i class="icon-anchor"> </i> Edit piratebadge.dart. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Add an import to the top of the file. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+import 'dart:html'; |
+ |
+[[highlight]]import 'dart:math' show Random;[[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+<i class="icon-key"> </i> <strong> Key Information </strong> |
+ |
+* Using the `show` keyword, |
+you can import only the classes, functions, or properties you need. |
+ |
+* `Random` provides a random number generator. |
+ |
+</div></div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Add a class declaration to the bottom of the file. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+... |
+ |
+[[highlight]]class PirateName { |
+}[[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* The class declaration provides the class name. |
+ |
+</div></div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Create a class-level Random object. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+class PirateName { |
+ [[highlight]]static final Random indexGen = new Random();[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* `static` defines a class-level field. That is, |
+the random number generator is shared with all |
+instances of this class. |
+ |
+* Dart Editor italicizes static names. |
+ |
+* Use `new` to call a constructor. |
+ |
+</div></div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Add two instance variables to class, |
+one for the first name and one for the appellation. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+class PirateName { |
+ static final Random indexGen = new Random(); |
+[[highlight]] String _firstName; |
+ String _appellation;[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Private variables start with underscore (`_`). |
+ |
+</div></div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Create two static lists within the class |
+that provide a small collection of names and appellations to choose from. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+class PirateName { |
+ ... |
+[[highlight]] static final List names = [ |
+ 'Anne', 'Mary', 'Jack', 'Morgan', 'Roger', |
+ 'Bill', 'Ragnar', 'Ed', 'John', 'Jane' ]; |
+ static final List appellations = [ |
+ 'Black','Damned', 'Jackal', 'Red', 'Stalwart', 'Axe', |
+ 'Young', 'Old', 'Angry', 'Brave', 'Crazy', 'Noble'];[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* `final` variables cannot change. |
+ |
+* Lists are built into the language. |
+These lists are created using list literals. |
+ |
+* The `List` class provides the API for lists. |
+ |
+</div></div> |
+ |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Provide a constructor for the class. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+class PirateName { |
+ ... |
+[[highlight]] PirateName({String firstName, String appellation}) { |
+ if (firstName == null) { |
+ _firstName = names[indexGen.nextInt(names.length)]; |
+ } else { |
+ _firstName = firstName; |
+ } |
+ if (appellation == null) { |
+ _appellation = appellations[indexGen.nextInt(appellations.length)]; |
+ } else { |
+ _appellation = appellation; |
+ } |
+ }[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Constructors have the same name as the class. |
+ |
+* The parameters enclosed in curly brackets (`{` and `}`) |
+are optional, named parameters. |
+ |
+* The `nextInt()` function gets a new random integer |
+from the random number generator. |
+ |
+* Use square brackets (`[` and `]`) to index into a list. |
+ |
+* The `length` property returns the number of items in a list. |
+ |
+* The code uses a random number as an index into the list. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Provide a getter for the pirate name. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+class PirateName { |
+ ... |
+[[highlight]] String get pirateName => |
+ _firstName.isEmpty ? '' : '$_firstName the $_appellation';[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div><div class="span5" markdown="1"> |
+ |
+* Getters are special methods that provide read access to an object’s properties. |
+ |
+* The ternary operator `?:` is short-hand for an if-then-else statement. |
+ |
+* String interpolation |
+(`'$_firstName the $_appellation'`) |
+lets you easily build strings from other objects. |
+ |
+* The fat arrow (` => expr; `) syntax is a shorthand for `{ return expr; }`. |
+ |
+</div></div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Modify the function `setBadgeName()` to use a PirateName instead of a String: |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void setBadgeName([[highlight]]PirateName[[/highlight]] newName) { |
+ querySelector('#badgeName').text = newName[[highlight]].pirateName[[/highlight]]; |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div><div class="span5" markdown="1"> |
+ |
+* This code calls the getter to get the PirateName as a string. |
+ |
+</div></div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Change `updateBadge()` to generate a PirateName based on the input field value. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void updateBadge(Event e) { |
+ String inputName = (e.target as InputElement).value; |
+ |
+ [[highlight]]setBadgeName(new PirateName(firstName: inputName));[[/highlight]] |
+ ... |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div><div class="span5" markdown="1"> |
+ |
+* The call to the constructor provides a value for one optional named parameter. |
+ |
+</div></div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Change `generateBadge()` to generate a PirateName instead of using `Anne Bonney`. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void generateBadge(Event e) { |
+ setBadgeName([[highlight]]new PirateName()[[/highlight]]); |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div><div class="span5" markdown="1"> |
+ |
+* In this case, the call to the constructor passes no parameters. |
+ |
+</div></div> |
+ |
+#### <i class="icon-anchor"> </i> Run the app. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Save your files with **File > Save All**. |
+ |
+Use the Run button |
+<img src="images/run.png" width="16" height="16" |
+ alt="Run button"> |
+in Dart Editor to run the app. |
+ |
+Compare your app to the one running below. |
+ |
+Type in the input field. |
+Remove the text from the input field. |
+Click the button. |
+ |
+<iframe class="running-app-frame" |
+ style="height:220px;width:530px;" |
+ src="examples/4-classbadge/piratebadge.html"> |
+</iframe> |
+ |
+ |
+##### Problems? |
+ |
+Check your code against the files in `4-classbadge`. |
+ |
+* [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/web/4-classbadge/piratebadge.html) |
+ |
+* [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/web/4-classbadge/piratebadge.dart) |
+ |
+</div> |
+ |
+ |
+<hr> |
+ |
+ |
+##Step 5: Save to local storage {#step-five} |
+ |
+In this step, you give the app some persistence |
+by saving the badge name to local storage each time it changes. |
+When you restart the app, |
+it initializes the badge from the saved name. |
+ |
+#### <i class="icon-anchor"> </i> Edit piratebadge.dart. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Import the JSON converter from the `dart:convert` library. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+import 'dart:html'; |
+import 'dart:math' show Random; |
+[[highlight]] |
+import 'dart:convert' show JSON;[[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+<i class="icon-key"> </i> <strong> Key Information </strong> |
+ |
+* `JSON` provides convenient access to the most common JSON use cases. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Add a named constructor to the PirateName class. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+class PirateName { |
+ ... |
+[[highlight]] PirateName.fromJSON(String jsonString) { |
+ Map storedName = JSON.decode(jsonString); |
+ _firstName = storedName['f']; |
+ _appellation = storedName['a']; |
+ }[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* The constructor creates a new PirateName instance from a JSON-encoded string. |
+ |
+* `PirateName.fromJson` is a named constructor. |
+ |
+* `JSON.decode()` parses a JSON string and creates Dart objects from it. |
+ |
+* The pirate name is decoded into a `Map` object. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Add a getter to the PirateName class |
+that encodes a pirate name in a JSON string. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+class PirateName { |
+ ... |
+ [[highlight]]String get jsonString => '{ "f": "$_firstName", "a": "$_appellation" } ';[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* The getter formats the JSON string using the map format. |
+ |
+</div> </div> |
+ |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Declare a top-level string. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+[[highlight]]final String TREASURE_KEY = 'pirateName';[[/highlight]] |
+ |
+void main() { |
+ ... |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* This string is a key to the local storage. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Save the pirate name when the badge name changes. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void setBadgeName(PirateName newName) { |
+ [[highlight]]if (newName == null) { |
+ return; |
+ }[[/highlight]] |
+ querySelector('#badgeName').text = newName.pirateName; |
+ [[highlight]]window.localStorage[TREASURE_KEY] = newName.jsonString;[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Local storage is provided by the browser's `Window`. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Add a top-level function called `getBadgeNameFromStorage()`. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void setBadgeName(PirateName newName) { |
+ ... |
+} |
+ |
+[[highlight]]PirateName getBadgeNameFromStorage() { |
+ String storedName = window.localStorage[TREASURE_KEY]; |
+ if (storedName != null) { |
+ return new PirateName.fromJSON(storedName); |
+ } else { |
+ return null; |
+ } |
+}[[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* The function retrieves the pirate name from local storage |
+and creates a PirateName object from it. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+<hr> |
+Call the function from the `main()` function. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void main() { |
+ ... |
+ [[highlight]]setBadgeName(getBadgeNameFromStorage());[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Initialize the badge name from local storage. |
+ |
+ {% comment %} non-breaking space required for bootstrap/markdown bogosity {% endcomment %} |
+ |
+</div> </div> |
+ |
+#### <i class="icon-anchor"> </i> Run the app. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Save your files with **File > Save All**. |
+ |
+Use the Run button |
+<img src="images/run.png" width="16" height="16" |
+ alt="Run button"> |
+in Dart Editor to run the app. |
+ |
+Compare your app to the one running below. |
+ |
+Click the button to put a name on the badge. |
+Start the app again by duplicating this window. |
+ |
+<iframe class="running-app-frame" |
+ style="height:220px;width:530px;" |
+ src="examples/5-localbadge/piratebadge.html"> |
+</iframe> |
+ |
+ |
+##### Problems? |
+ |
+Check your code against the files in `5-localbadge`. |
+ |
+* [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/web/5-localbadge/piratebadge.html) |
+ |
+* [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/web/5-localbadge/piratebadge.dart) |
+ |
+</div> |
+ |
+ |
+<hr> |
+ |
+ |
+##Step 6: Read names from JSON-encoded file {#step-six} |
+ |
+In this step, you change the PirateName class to get |
+the list of names and appellations from a JSON file. |
+This gives you a chance to add more names and |
+appellations to the program. |
+ |
+#### <i class="icon-anchor"> </i> Create piratenames.json. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Use **File > New File...** to create a JSON-encoded file |
+named `piratenames.json` with the following content. |
+ |
+Put the file in `1-blankbadge` alongside the Dart and HTML files you've been editing. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+{ "names": [ "Anne", "Bette", "Cate", "Dawn", |
+ "Elise", "Faye", "Ginger", "Harriot", |
+ "Izzy", "Jane", "Kaye", "Liz", |
+ "Maria", "Nell", "Olive", "Pat", |
+ "Queenie", "Rae", "Sal", "Tam", |
+ "Uma", "Violet", "Wilma", "Xana", |
+ "Yvonne", "Zelda", |
+ "Abe", "Billy", "Caleb", "Davie", |
+ "Eb", "Frank", "Gabe", "House", |
+ "Icarus", "Jack", "Kurt", "Larry", |
+ "Mike", "Nolan", "Oliver", "Pat", |
+ "Quib", "Roy", "Sal", "Tom", |
+ "Ube", "Val", "Walt", "Xavier", |
+ "Yvan", "Zeb"], |
+ "appellations": [ "Awesome", "Black", "Captain", "Damned", |
+ "Even", "Fighter", "Great", "Hearty", |
+ "Irate", "Jackal", "King", "Lord", |
+ "Mighty", "Noble", "Old", "Powerful", |
+ "Quick", "Red", "Stalwart", "Tank", |
+ "Ultimate", "Vicious", "Wily", "aXe", |
+ "Young", "Zealot", |
+ "Angry", "Brave", "Crazy", "Damned", |
+ "Eager", "Fool", "Greedy", "Hated", |
+ "Idiot", "Jinxed", "Kind", "Lame", |
+ "Maimed", "Naked", "Old", "Pale", |
+ "Queasy", "Rat", "Sandy", "Tired", |
+ "Ugly", "Vile", "Weak", "Xeric", |
+ "Yellow", "Zesty"]} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratenames.json</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+<i class="icon-key"> </i> <strong> Key Information </strong> |
+ |
+* The file contains a JSON-encoded map, |
+which contains two lists of strings. |
+ |
+</div> </div> |
+ |
+#### <i class="icon-anchor"> </i> Edit piratebadge.html. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Disable the input field and the button. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify html %} |
+... |
+ <div> |
+ <input type="text" id="inputName" maxlength="15" [[highlight]]disabled[[/highlight]]> |
+ </div> |
+ <div> |
+ <button id="generateButton" [[highlight]]disabled[[/highlight]]>Aye! Gimme a name!</button> |
+ </div> |
+... |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.html</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+ |
+* The Dart code enables the text field and |
+the button after the pirate names are successfully read from |
+the JSON file. |
+ |
+</div> </div> |
+ |
+#### <i class="icon-anchor"> </i> Edit piratebadge.dart. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Add an import to the top of the file. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+import 'dart:html'; |
+import 'dart:math' show Random; |
+import 'dart:convert' show JSON; |
+ |
+[[highlight]]import 'dart:async' show Future;[[/highlight]] |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* The `dart:async` library provides for asynchronous programming. |
+ |
+* A `Future` provides a way to get a value in the future. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+Replace the `names` and `appellations` lists with these static, empty lists: |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+class PirateName { |
+ ... |
+ [[highlight]]static List<String> names = []; |
+ static List<String> appellations = [];[[/highlight]] |
+ ... |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Be sure to remove `final` from these declarations. |
+ |
+* `[]` is equivalent to `new List()`. |
+ |
+* A List is a _generic_ type—a List can contain any kind of object. |
+If you intend for a list to contain only strings, |
+you can declare it as `List<String>`. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+<hr> |
+ |
+Add two static functions to the PirateName class: |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+class PirateName { |
+ ... |
+ |
+ [[highlight]]static Future readyThePirates() { |
+ var path = 'piratenames.json'; |
+ return HttpRequest.getString(path) |
+ .then(_parsePirateNamesFromJSON); |
+ } |
+ |
+ static _parsePirateNamesFromJSON(String jsonString) { |
+ Map pirateNames = JSON.decode(jsonString); |
+ names = pirateNames['names']; |
+ appellations = pirateNames['appellations']; |
+ }[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* `HttpRequest` is a utility for retrieving data from a URL. |
+ |
+* `getString()` is a convenience method for doing a simple |
+GET request that returns a string. |
+ |
+* The code uses a `Future` to perform the GET asynchronously. |
+ |
+* The callback function for `.then()` is called when |
+the Future completes successfully. |
+ |
+* When the Future completes successfully, |
+the pirate names are read from the JSON file. |
+ |
+* `readyThePirates` returns the Future so the main program has the |
+opportunity to do something after the file is read. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+<hr> |
+Add a top-level variable. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+[[highlight]]SpanElement badgeNameElement;[[/highlight]] |
+ |
+void main() { |
+ ... |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Stash the span element for repeated use instead of querying the DOM for it. |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+<hr> |
+Make these changes to the `main()` function. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void main() { |
+ [[highlight]]InputElement inputField = querySelector('#inputName'); |
+ inputElement.onInput.listen(updateBadge);[[/highlight]] |
+ genButton = querySelector('#generateButton'); |
+ genButton.onClick.listen(generateBadge); |
+ |
+ [[highlight]]badgeNameElement = querySelector('#badgeName');[[/highlight]] |
+ ... |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Stash the span element in the global variable. |
+Also, stash the input element in a local variable. |
+ |
+ |
+</div> </div> |
+ |
+<div class="trydart-step-details" markdown="1"> |
+<hr> |
+Then, add the code to get the names from the JSON file, |
+handling both success and failure. |
+</div> |
+ |
+<div class="row"> <div class="span7"> |
+ |
+<div class="trydart-step-details"> |
+{% prettify dart %} |
+void main() { |
+ ... |
+ |
+[[highlight]] PirateName.readyThePirates() |
+ .then((_) { |
+ //on success |
+ inputField.disabled = false; //enable |
+ genButton.disabled = false; //enable[[/highlight]] |
+ setBadgeName(getBadgeNameFromStorage()); |
+ [[highlight]]}) |
+ .catchError((arrr) { |
+ print('Error initializing pirate names: $arrr'); |
+ badgeNameElement.text = 'Arrr! No names.'; |
+ });[[/highlight]] |
+} |
+{% endprettify %} |
+</div> |
+ |
+<div class="trydart-filename">piratebadge.dart</div> |
+ |
+</div> <div class="span5" markdown="1"> |
+ |
+* Call the `readyThePirates()` function, |
+which returns a Future. |
+ |
+* When the Future successfully completes, |
+the `then()` callback function is called. |
+ |
+* Using underscore (`_`) as a parameter name |
+indicates that the parameter is ignored. |
+ |
+* The callback function enables the UI |
+and gets the stored name. |
+ |
+* If the Future encounters an error |
+the `catchError` callback function is called |
+and the program displays an error message, |
+leaving the UI disabled. |
+ |
+* The callback functions for `then()` and `catchError` are defined inline. |
+ |
+</div> </div> |
+ |
+#### <i class="icon-anchor"> </i> Run the app. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Save your files with **File > Save All**. |
+ |
+Use the Run button |
+<img src="images/run.png" width="16" height="16" |
+ alt="Run button"> |
+in Dart Editor to run the app. |
+ |
+If you want to see what happens when the app can't find the `.json` file, |
+change the file name in the code and run the program again. |
+ |
+Compare your app to the final version running below. |
+ |
+ |
+<iframe class="running-app-frame" |
+ style="height:220px;width:530px;" |
+ src="examples/6-piratebadge_json/piratebadge.html"> |
+</iframe> |
+ |
+ |
+##### Problems? |
+ |
+Check your code against the files in `6-piratebadge_json`. |
+ |
+* [piratebadge.html](https://github.com/dart-lang/one-hour-codelab/blob/master/web/6-piratebadge_json/piratebadge.html) |
+ |
+* [piratebadge.dart](https://github.com/dart-lang/one-hour-codelab/blob/master/web/6-piratebadge_json/piratebadge.dart) |
+ |
+</div> |
+ |
+{% comment %} |
+ |
+#### <i class="icon-anchor"> </i> Share your pirate name. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Congratulations! You finished the pirate badge code lab. |
+ |
+ |
+Share your pirate name with the world. |
+ |
+<p class="share-button twitter"> |
+<a href="https://twitter.com/share" |
+ class="twitter-share-button external-link" |
+ data-count="none" |
+ data-text="Arrr! I've generated me pirate name and learnt Dart, to boot. http://dartlang.org/darrrt" |
+ data-hashtags="dartlang">Tweet</a> |
+ </p> |
+ |
+<script src="https://apis.google.com/js/plusone.js"></script> |
+<g:plus action="share"></g:plus> |
+ |
+</div> |
+{% endcomment %} |
+ |
+ |
+<hr> |
+ |
+##Step 7: Go forth and learn more about Dart {#step-seven} |
+ |
+#### <i class="icon-anchor"> </i> Think about what you've done! |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+This code lab provided a tour of most Dart language features |
+and many library features. |
+Here's where to go to learn more. |
+ |
+##### The Dart language |
+ |
+<a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html"> |
+A Tour of the Dart Language</a> |
+shows you how to use each major Dart feature, |
+from variables and operators to classes and libraries. |
+This code lab introduced the following Dart language features, |
+all of which are covered in more detail in the language tour. |
+ |
+* string interpolation (`'$_firstName the $_appellation'`) |
+* the cascade operator (`..`) |
+* the fat arrow (`=>`) function syntax |
+* the ternary operator (`?:`) |
+* named constructors (`PirateName.fromJSON(...)`) |
+* optional parameters |
+* a class |
+* getters |
+* instance methods and fields |
+* class level methods and fields |
+* top-level variables and functions |
+* typecasting with `as` (`(e.target as InputElement)`) |
+* import, and import with `show` (`import 'dart:math' show Random;`) |
+* generics |
+ |
+##### The Dart libraries |
+ |
+<a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html"> |
+A Tour of the Dart Libraries</a> |
+shows you how to use the major features in Dart’s libraries. |
+ |
+##### API documentation for classes |
+ |
+<a href="https://api.dartlang.org/dart_core/String.html" target="_blank">String</a>, |
+<a href="https://api.dartlang.org/dart_core/List.html" target="_blank">List</a>, |
+<a href="https://api.dartlang.org/dart_core/Map.html" target="_blank">Map</a>, |
+<a href="https://api.dartlang.org/dart_math/Random.html" target="_blank">Random</a>, |
+<a href="https://api.dartlang.org/dart_html/InputElement.html" target="_blank">InputElement</a>, |
+<a href="https://api.dartlang.org/dart_html/ButtonElement.html" target="_blank">ButtonElement</a>, |
+<a href="https://api.dartlang.org/dart_html/Event.html" target="_blank">Event</a>, |
+<a href="https://api.dartlang.org/dart_html/HttpRequest.html" target="_blank">HttpRequest</a>, and |
+<a href="https://api.dartlang.org/dart_async/Future.html" target="_blank">Future</a> |
+ |
+##### API documentation for libraries |
+ |
+<a href="https://api.dartlang.org/dart_core.html" target="_blank">dart:core</a>, |
+<a href="https://api.dartlang.org/dart_math.html" target="_blank">dart:math</a>, |
+<a href="https://api.dartlang.org/dart_html.html" target="_blank">dart:html</a>, |
+<a href="https://api.dartlang.org/dart_async.html" target="_blank">dart:async</a>, and |
+<a href="https://api.dartlang.org/dart_convert.html" target="_blank">dart:convert</a> |
+ |
+##### API documentation for JSON and local storage |
+ |
+<a href="https://api.dartlang.org/dart_html/Window.html#localStorage" target="_blank">LocalStorage</a>, and |
+<a href="https://api.dartlang.org/dart_convert.html#JSON" target="_blank">JSON</a> |
+ |
+ |
+</div> |
+ |
+#### <i class="icon-anchor"> </i> Check out the samples. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+ |
+Run some Dart programs online and check out the source code |
+on our [Samples page](/samples/). |
+</div> |
+ |
+#### <i class="icon-anchor"> </i> Read the tutorials. |
+ |
+<div class="trydart-step-details" markdown="1"> |
+Learn more about Dart from |
+the [Dart tutorials](/docs/tutorials/). |
+</div> |
+ |