Skip to content

Commit

Permalink
Finalize the Weather Report Guide
Browse files Browse the repository at this point in the history
- Add a Result section at the end
- Pin the JS Bins to specific versions instead of their latest versions
- Make the spacing consistent in the code examples
- Minor spelling & grammar fixes

Closes #3121
  • Loading branch information
chasenlehara committed Mar 28, 2017
1 parent 7207f2f commit 6a8df3b
Showing 1 changed file with 90 additions and 83 deletions.
173 changes: 90 additions & 83 deletions docs/can-guides/commitment/recipes/weather-report/weather-report.md
Expand Up @@ -9,26 +9,26 @@ CanJS 3.5.

The final widget looks like:

<a class="jsbin-embed" href="https://jsbin.com/ruculey/embed?js,output">JS Bin on jsbin.com</a>
<a class="jsbin-embed" href="https://jsbin.com/ruculey/2/embed?js,output">JS Bin on jsbin.com</a>

To use the widget:

1. __Enter__ a location (example: `Chicago`)
2. If the location name isn't unique, __click__ on the intended location.
3. See the 10 day forecast for your selected city.
2. If the location name isnt unique, __click__ on the intended location.
3. See the 10-day forecast for your selected city.

__Start this tutorial by cloning the following JSBin__:

<a class="jsbin-embed" href="https://jsbin.com/ramokiw/embed?html,output">JS Bin on jsbin.com</a>
<a class="jsbin-embed" href="https://jsbin.com/ramokiw/2/embed?html,output">JS Bin on jsbin.com</a>

This JSBin has initial prototype HTML and CSS which is useful for
getting the application to look right.

The following sections are broken down into:

- Problem - A description of what the section is trying to accomplish.
- Things to know - Information about CanJS that is useful for solving the problem.
- Solution - The solution to the problem.
- Problem A description of what the section is trying to accomplish.
- Things to know Information about CanJS that is useful for solving the problem.
- Solution The solution to the problem.


## Setup
Expand Down Expand Up @@ -56,7 +56,7 @@ Get the basic setup for a CanJS app (in a JSBin) setup by:

```js
var Type = can.DefineMap.extend({
message: "string"
message: "string"
});
```

Expand All @@ -66,10 +66,10 @@ Get the basic setup for a CanJS app (in a JSBin) setup by:

```js
var MessageViewModel = can.DefineMap.extend({
message: "string"
message: "string"
});
var messageVM = new MessageViewModel();

var messageVM = new MessageViewModel();
var frag = template(messageVM)
```

Expand Down Expand Up @@ -109,8 +109,10 @@ document.body.appendChild(frag);

### The problem

We want an input element where a person can type a location to search for weather
and to show the user the location they typed.
We want an `input` element to:

- Allow a person to type a location to search for weather.
- Show the user the location they typed.

### Things to know

Expand All @@ -122,7 +124,7 @@ and to show the user the location they typed.
property: "string"
})
```
- The [can-stache-bindings.toParent] can set an input's `value` to
- The [can-stache-bindings.toParent] can set an inputs `value` to
a ViewModel property like:

```html
Expand All @@ -142,7 +144,7 @@ and to show the user the location they typed.
Update the template in the `HTML` tab to:

1. Update `location` on the ViewModel when the input changes.
2. Show value of the ViewModel's `location` property.
2. Show value of the ViewModels `location` property.

```html
<script id="app-template" type="text/stache">
Expand Down Expand Up @@ -177,14 +179,14 @@ document.body.appendChild(frag);
```
@highlight 2

## Get and display the places for the user's location name
## Get and display the places for the users location name

### The problem

Once the user has entered a location name, we need to get which
"place" it is. For example, a user might enter Paris, but we don't know if
place it is. For example, a user might enter Paris, but we dont know if
they mean the Paris in France or the one in Illinois. We need to get a
list of matching places for the location name, and display the matching places
list of matching places for the location name and display the matching places
on the page.

### Things to know
Expand All @@ -196,10 +198,10 @@ on the page.
```js
DefineMap.extend({
message: "string",
get excitedMessage(){
return this.message+"!";
}
})
get excitedMessage(){
return this.message+"!";
}
});
```

- [YQL](https://developer.yahoo.com/yql/console/) provides a service endpoint for
Expand All @@ -212,11 +214,11 @@ on the page.
q=select * from geo.places where text="Paris"
```

The list of matched places will be in the response data's `data.query.results.place` property.
The list of matched places will be in the response datas `data.query.results.place` property.
If there is only a single match, `place` will be an object instead of an array.

- The [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) is an easy way to make requests
to a url and get back JSON. Use it like:
to a URL and get back JSON. Use it like:

```js
fetch(url).then(function(response){
Expand All @@ -242,8 +244,8 @@ on the page.

### The solution

1. Show a "Loading places..." message while we wait on data.
2. Once the places are resolved, list each place's name, state, country and type of place.
1. Show a Loading places…” message while we wait on data.
2. Once the places are resolved, list each places name, state, country and type.

Update the template in the `HTML` tab to:

Expand All @@ -257,7 +259,7 @@ Update the template in the `HTML` tab to:
{{#if placesPromise.isPending}}
<p class="loading-message">
Loading places...
Loading places
</p>
{{/if}}
Expand Down Expand Up @@ -292,22 +294,22 @@ var WeatherViewModel = can.DefineMap.extend({
location: "string",
get placesPromise(){
if(this.location && this.location.length > 2) {
return fetch(
yqlURL+
can.param({
q: 'select * from geo.places where text="'+this.location+'"',
format: "json"
})
).then(function(response){
return response.json();
}).then(function(data){
console.log(data);
if(Array.isArray(data.query.results.place)) {
return data.query.results.place;
} else {
return [data.query.results.place];
}
});
return fetch(
yqlURL +
can.param({
q: 'select * from geo.places where text="'+this.location+'"',
format: "json"
})
).then(function(response){
return response.json();
}).then(function(data){
console.log(data);
if(Array.isArray(data.query.results.place)) {
return data.query.results.place;
} else {
return [data.query.results.place];
}
});
}
}
});
Expand All @@ -331,7 +333,7 @@ When a user clicks on a place, we need to indicate their selection.
- Use [can-stache-bindings.event ($EVENT)] to listen to an event on an element and call a method in `can-stache`. For example, the following calls `doSomething()` when the `<div>` is clicked.

```html
<div ($click)="sayHi()"> ... </div>
<div ($click)="sayHi()"> </div>
```

- `this` in a stache template refers to the current context of a template or section.
Expand All @@ -353,25 +355,25 @@ When a user clicks on a place, we need to indicate their selection.
```


- The [http://canjs.com/doc/can-define.types.html "any" type] can be used to define a property as
- The [http://canjs.com/doc/can-define.types.html any type] can be used to define a property as
accepting any data type like:

```js
var MessageViewModel = can.DefineMap.extend({
message: "string",
metaData: "any"
message: "string",
metaData: "any"
})
```

- `can.DefineMap` can also have methods:

```js
var MessageViewModel = can.DefineMap.extend({
message: "string",
metaData: "any",
sayHi: function(){
this.message = "Hello";
}
message: "string",
metaData: "any",
sayHi: function(){
this.message = "Hello";
}
});
```

Expand All @@ -392,7 +394,7 @@ Update the template in the `HTML` tab to:
{{#if placesPromise.isPending}}
<p class="loading-message">
Loading places...
Loading places
</p>
{{/if}}
Expand Down Expand Up @@ -467,7 +469,7 @@ document.body.appendChild(frag);

### The problem

Once we've selected a place, we need to get and display the forecast data for the
Once weve selected a place, we need to get and display the forecast data for the
selected place.

### Things to know
Expand All @@ -479,8 +481,8 @@ selected place.
```

- [YQL](https://developer.yahoo.com/yql/console/) provides a service endpoint for
retrieving a forecast that matches a `place`'s `woeid`. For example, the following requests the forecast
for Paris, France's `woeid`:
retrieving a forecast that matches a `place`s `woeid`. For example, the following requests the forecast
for Paris, Frances `woeid`:

```
https://query.yahooapis.com/v1/public/yql?
Expand All @@ -494,8 +496,8 @@ selected place.

Update the template in the `HTML` tab to:

1. Display each forecast day's details (date, text, high, and low).
2. Use the `toClassName` method to convert the forecast's `text` into a `className` value that
1. Display each forecast days details (date, text, high, and low).
2. Use the `toClassName` method to convert the forecasts `text` into a `className` value that
will be matched by the stylesheet.

```html
Expand All @@ -508,7 +510,7 @@ Update the template in the `HTML` tab to:
{{#if placesPromise.isPending}}
<p class="loading-message">
Loading places...
Loading places
</p>
{{/if}}
Expand All @@ -526,7 +528,7 @@ Update the template in the `HTML` tab to:
{{#if place}}
<div class="forecast">
<h1>10 day {{place.name}} Weather Forecast</h1>
<h1>10-day {{place.name}} Weather Forecast</h1>
<ul>
{{#each forecastPromise.value}}
<li>
Expand Down Expand Up @@ -615,7 +617,7 @@ document.body.appendChild(frag);
### The problem

Currently, if the user changes the entered location, the weather forecast for the
other city is still visible. Lets hide it!
other city is still visible. Let’s hide it!

### Things to know

Expand Down Expand Up @@ -718,16 +720,16 @@ user to select their place; instead, we should show the forecast immediately.

```js
var MessageVM = can.DefineMap.extend({
username: "string",
message: {
get: function(lastSet) {
if(lastSet) {
return lastSet;
} else {
return "Hello "+this.username;
}
}
}
username: "string",
message: {
get: function(lastSet) {
if(lastSet) {
return lastSet;
} else {
return "Hello "+this.username;
}
}
}
});

var messageVM = new MessageVM({username: "Hank"});
Expand All @@ -741,15 +743,15 @@ user to select their place; instead, we should show the forecast immediately.

```js
var MessageVM = can.DefineMap.extend({
messageId: "string",
message: {
get: function(lastSet, resolve) {
fetch("/message/"+this.messageId)
.then(function(response){
return response.json();
}).then(resolve);
}
}
messageId: "string",
message: {
get: function(lastSet, resolve) {
fetch("/message/"+this.messageId)
.then(function(response){
return response.json();
}).then(resolve);
}
}
});
```

Expand All @@ -769,7 +771,7 @@ Update the template in the `HTML` tab to:
{{#if placesPromise.isPending}}
<p class="loading-message">
Loading places...
Loading places
</p>
{{/if}}
Expand Down Expand Up @@ -809,8 +811,8 @@ Update the template in the `HTML` tab to:
Update the `JS` tab to:

1. Define a `places` property that will have the places list returned by the `YQL` service.
2. Define a `showPlacePicker` property that is true if there's more than one places in `place` and
the `place` property hasn't been set yet.
2. Define a `showPlacePicker` property that is true if theres more than one place in `places` and
the `place` property hasnt been set yet.
3. Update the `place` property to default to the first item in `places` if there is only one item.

```js
Expand Down Expand Up @@ -887,7 +889,7 @@ var WeatherViewModel = can.DefineMap.extend({
}
},
toClassName: function(text){
return text.toLowerCase().replace(/ /g, "-");
return text.toLowerCase().replace(/ /g, "-");
}
});

Expand All @@ -899,5 +901,10 @@ document.body.appendChild(frag);
```
@highlight 30-51,only

## Result

When finished, you should see something like the following JS Bin:

<a class="jsbin-embed" href="https://jsbin.com/ruculey/2/embed?js,output">JS Bin on jsbin.com</a>

<script src="https://static.jsbin.com/js/embed.min.js?3.35.5"></script>

0 comments on commit 6a8df3b

Please sign in to comment.