<style>
.scrollable pre {
    overflow-y: auto;
    max-height: 40em;
    -webkit-overflow-scrolling: touch;
}

.screenshot {
    display: block;
    width: 584px;
    margin: 0 auto;
}
</style>

{{>app-contributors-js-mock-config}}

<div class="intro">
{{! TODO:
  * Provide more of an intro to the apps organization. Expand on this in a section after the rendered example, but before the code.
}}
<p>
This example demonstrates the powerful navigation and view management features `Y.App` provides by creating an application to browse through the contributors of GitHub projects.</p>

<p><strong>Note:</strong> If the GitHub API is unavailable, you can <a href="app-contributors.html?mock=true">try this example with mock data</a>. The available users in the mock example are `yui` and `ericf`.
</p>
</div>


<section>
<div class="example">
    {{>app-contributors-css}}
    {{>app-contributors-templates}}
    {{>app-contributors-js}}
    <div id="github-app"></div>
</div>
</section>


<h2>HTML</h2>

<p>
This application starts with a bare container which will be used to define the bounds of the app and provide a place for it to render its contents.
</p>

```
<div id="github-app"></div>
```

<h3>Templates</h3>

<p>
This app makes heavy use of <a href="../handlebars/index.html">Handlebars</a> templates to create reusable chunks of HTML which will be used by our views render the different "pages" and sections of our app.
</p>

<p>
These templates, while being placed within the markup of the page, are invisible and not rendered by the browser. By putting the templates inside of a `<script>` elements with `type="text/x-handlebars-template"`, the browser will ignore its contents (and therefore not try to execute it as a script) because it doesn't recognize the `text/x-handlebars-template` content-type.
</p>

<p>
You'll notice all of these `<script>` elements contain `id` attributes; this allows us to easily reference a template by-id and retrieve its contents as a string which can by compiled into a Handlebars template function.
</p>

<p>
This is generally a more maintainable way of embedding templates than storing them in JavaScript strings, but there's no requirement that you use this technique.
</p>

<div class="scrollable">
```handlebars
{{>app-contributors-templates}}
```
</div>


<h2>CSS</h2>

<p>
To make our app look nice, we'll add some CSS to style the markup we've setup in our [[#templates]]. We'll also use the excellent <a href="../cssgrids/index.html">CSS Grids</a> in YUI to help us layout the different parts of the app's interface (you might have noticed the references to the CSS Grids classes in our templates).
</p>

<div class="scrollable">
```
{{>css-yui-grids}}
{{>app-contributors-css}}
```
</div>


<h2>JavaScript</h2>

<p>
Our GitHub Contributors app will have its code organized into three main areas:
</p>

<ol>
    <li>
        <p>
        [[#Models &amp; Model Lists]] which manage, store, and load the data for our application. All the data will be fetched from <a href="http://developer.github.com/v3/">GitHub's API</a>; we'll extract the logic for interacting with the API out into a [[#`GithubSync`]] extension so it can be reused.
        </p>
    </li>
    <li>
        <p>
        [[#Views]] which represent discrete, render-able, pieces of our app's user interface by bringing together our models and model lists with our templates and handling the user interactions that occur within their containment.
        </p>
    </li>
    <li>
        <p>
        The [[#App]] component, a navigation and view manager, provides a foundation and structure which allows us to declaratively connect the parts of our application together into higher-level "pages" and handles the user navigating between them.
        </p>
    </li>
</ol>

<p>
All of these things will live inside the following YUI instance:
</p>

```
{{>js-yui-seed}}
{{>app-contributors-js-yui-start}}
    // ... Add the code from the following sections here! ...
{{>app-contributors-js-yui-end}}
```

<h3>GithubSync</h3>

<p>
This is an extension that provides a read-only sync implementation for <a href="http://developer.github.com/v3/">GitHub's API</a> which can be mixed-in by a <a href="../model/index.html">`Y.Model`</a> or <a href="../model-list/index.html">`Y.ModelList`</a> subclass. This extension is used by [[#`User`]], [[#`RepoList`]], and [[#`ContributorList`]] as we'll see below.
</p>

<p>
We have this ability to create mixable feature extensions, like this sync implementation, because `Model` and `ModelList` are <a href="../base/index.html#extensions">`Y.Base`</a>-based.
</p>

```
{{>app-contributors-js-github-sync}}
```

<h3>Models &amp; Model Lists</h3>

<p>
To keep our code organized and maintainable, we want a clear separation of concerns. Let's start by looking at our application from a data-centric point of view. We've already reviewed the <a href="http://developer.github.com/v3/">GitHub API</a> and abstracted-out the communication with the API into a [[#`GithubSync`]] extension which we'll mix into certain <a href="../model/index.html">Models</a> and <a href="../model-list/index.html">Model Lists</a> of our app.
</p>

<p>
Our app has three main entities: users, repositories, and contributors; all of which clearly fit with our application's features. To model these entities, we'll create the following `Y.Model` subclasses: [[#`User`]], [[#`Repo`]], and [[#`Contributor`]]. We'll also need `Y.ModelList` subclasses for our `Repo` and `Contributor` models: [[#`RepoList`]], and [[#`ContributorList`]].
</p>

<p>
Let's look at each of these in detail:
</p>

<h4>User</h4>

<p>
The `User` model contains only the data attributes from the <a href="http://developer.github.com/v3/users/">GitHub Users API</a> which are relevant to the app. The [[#`GithubSync`]] extension is mixed-in and provides the necessary communication with this API.
</p>

```
{{>app-contributors-js-user}}
```

<h4>Repo</h4>

<p>
The `Repo` model contains only the data attributes from the <a href="http://developer.github.com/v3/repos/">GitHub Repos API</a> which are relevant to the app.
</p>

```
{{>app-contributors-js-repo}}
```

<h4>RepoList</h4>

<p>
Our app will display a list of [[#`Repo`]]s for a [[#`User`]]. The `RepoList` class will add collection semantics for `Repo`s by extending `Y.ModelList`. The [[#`GithubSync`]] extension is also mixed-in to provide communication with the <a href="http://developer.github.com/v3/repos/">GitHub Repos API</a>.
</p>

```
{{>app-contributors-js-repolist}}
```

<h4>Contributor</h4>

<p>
The `Contributor` model extends the [[#`User`]] model and adds one additional data attribute, `contributions`.
</p>

```
{{>app-contributors-js-contributor}}
```

<h4>ContributorList</h4>

<p>
Our app will display a list of [[#`Contributor`]]s for a [[#`Repo`]]. The `ContributorList` class will add collection semantics for `Contributor`s by extending `Y.ModelList`. The [[#`GithubSync`]] extension is also mixed-in to provide communication with the <a href="http://developer.github.com/v3/repos/">GitHub Repos API</a>.
</p>

```
{{>app-contributors-js-contributorlist}}
```

<h3>Views</h3>

<p>
We've separated our data-related logic from our presentation by creating our models and model lists; we'll continue this by keeping our presentation-logic separate from our [[#templates]], and create <a href="../view/index.html">View</a> classes which contain the presentation-related logic that can render a model or model list using a template.
</p>

<p>
The data model for our app consists of many numerical values which our views will need to display with labels. Before we dig into the views, let's first create a helper function we can use to add these labels to the data object we pass to our templates:
</p>

```
{{>app-contributors-js-utilities}}
```

<p>
The views for our app will be pretty trivial; they mainly just prepare the model or model list data and apply it to the corresponding template during rendering. Usually your views would involve handling of DOM events created by user interactions and binding to the model or model list changes so the view can be updated or re-rendered. We'll create the following views by sub-classing `Y.View`: [[#`UserView`]], [[#`RepoView`]], [[#`RepoListView`]], and [[#`ContributorListView`]].
</p>

<p>
Let's look at where and how each of the views will be used:
</p>

<h4>UserView</h4>

<p>
The `UserView` is responsible for the rendering the info and stats about the currently-selected GitHub user. Using the [[#Templates|User Template]] this view renders a [[#User|`User` Model]] to look like this:
</p>

<p>
<img class="screenshot" src="{{componentAssets}}/user-view.png" alt="Screenshot of the UserView rendering the yui GitHub User." />
</p>

```
{{>app-contributors-js-user-view}}
```

<h4>RepoView</h4>

<p>
The `RepoView` is responsible for the rendering the info and stats about the currently-selected GitHub repository. Using the [[#Templates|Repo Template]] this view renders a [[#Repo|`Repo` Model]] to look like this:
</p>

<p>
<img class="screenshot" src="{{componentAssets}}/repo-view.png" alt="Screenshot of the RepoView rendering the yui/yui3 GitHub repository." />
</p>

```
{{>app-contributors-js-repo-view}}
```

<h4>RepoListView</h4>

<p>
The `RepoListView` is responsible for the rendering a list of repositories/projects for the currently-selected GitHub user. Using the [[#Templates|RepoList Template]] this view renders a [[#`RepoList`]] to look like this:
</p>

<p>
<img class="screenshot" src="{{componentAssets}}/repo-list-view.png" alt="Screenshot of the RepoListView rendering the GitHub repos for YUI." />
</p>

```
{{>app-contributors-js-repolist-view}}
```

<h4>ContributorListView</h4>

<p>
The `ContributorListView` is responsible for the rendering a list of contributors for the currently-selected GitHub repository/project. Using the [[#Templates|ContributorList Template]] this view renders a [[#`ContributorList`]] to look like this:
</p>

<p>
<img class="screenshot" src="{{componentAssets}}/contributor-list-view.png" alt="Screenshot of the ContributorListView rendering the GitHub contributors to YUI." />
</p>

```
{{>app-contributors-js-contributorlist-view}}
```

<h3>App</h3>

<p>
At this point we have the code for our app organized such that our models, views, and templates have distinct boundaries and roles while being loosely-coupled. We have a great separation of concerns, but now we need a way to group these pieces into "pages", create a URL-space for the app, and respond when the user navigates around our app.
</p>

<p>
`Y.App` provides a foundation and structure for creating a top-level application component which is pefect for tying together the parts of an application. We'll create a `Y.App` subclass that will serve as our navigation and view manager; this is where we'll define our URL-space, handle when the user navigates to those URLs, and respond by fetching the data we need and showing the corresponding page of our app.
</p>

<p>
In the section that follow, we'll define our app's URL-space and what data we'll need to respond at each URL, create some page-level views, then implement our `Y.App` subclass: [[#`ContributorsApp`]].
</p>

<h4>Page Views</h4>

<p>
We will now group our [[#Views]] into "pages" to implement the three main features of our app. We'll combine the views we've already created into composite page-level views: [[#`HomePageView`]], [[#`UserPageView`]], and [[#`RepoPageView`]].
</p>

<p>
Let's look at each page view in some detail:
</p>

<h5>HomePageView</h5>

<p>
This view will handle the user interaction of choosing a particular GitHub user by listening for changes to a text input after a username is entered. The view will also fire a `changeUser` event to which our app can respond.
</p>

```
{{>app-contributors-js-homepage-view}}
```

<h5>UserPageView</h5>

<p>
This view is a composite of a [[#`UserView`]] and a [[#`RepoListView`]] which will display the information and stats about a GitHub user along with a list of their public repositories/projects.
</p>

```
{{>app-contributors-js-userpage-view}}
```

<h5>RepoPageView</h5>

<p>
This view is a composite of a [[#`RepoView`]] and a [[#`ContributorListView`]] which will display the information and stats about a GitHub user's particular repository/project along with a list of all the GitHub users which are contributors to that project.
</p>

```
{{>app-contributors-js-repopage-view}}
```

<h4>Routes</h4>

<p>
With our app grouped into three "pages", we need to make these pages accessible via URLs; we'll do this by defining the following routes:
</p>

<ul>
    <li>
        <p>
        <b>`/`</b>: Displays the [[#`HomePageView`]] and uses the current [[#`User`]] model to pre-fill the text input.
        </p>
    </li>
    <li>
        <p>
        <b>`/github/:user/`</b>: Displays the [[#`UserPageView`]] which requires a [[#`User`]] model and [[#`RepoList`]] model list which we'll setup through the following steps:
        </p>

        <ol>
            <li>
            Retrieve the GitHub username from the `:user` request parameter and create a `User` model.
            </li>
            <li>
            Load our user model's data from the GitHub API.
            </li>
            <li>
            Assign our fully-loaded user model to a `RepoList` model list instance.
            </li>
            <li>
            Load our repos model-list to get all our user's `Repo`s from the GitHub API.
            </li>
        </ol>
    </li>
    <li>
        <p>
        <b>`/github/:user/:repo/`</b>: Displays the [[#`RepoPageView`]] which requires a [[#`Repo`]] model and [[#`ContributorList`]] model list which we'll setup through the following steps (Note: how steps 1–4 are the same as above):
        </p>

        <ol>
            <li>
            Retrieve the GitHub username from the `:user` request parameter and create a `User` model.
            </li>
            <li>
            Load our user model's data from the GitHub API.
            </li>
            <li>
            Assign our fully-loaded user model to a `RepoList` model list instance.
            </li>
            <li>
            Load our repos model-list to get all our user's `Repo`s from the GitHub API.
            </li>
            <li>
            Retrieve the specific repository name from the `:repo` request parameter and find the corresponding `Repo` model in our `RepoList`.
            </li>
            <li>
            Assign our repo model to a `ContributorList` model list instance.
            </li>
            <li>
            Load our contributors model-list from the GitHub API to get all of the GitHub users who have contributed to the project.
            </li>
        </ol>
    </li>
</ul>

<p>
Notice how our `/github/:user/` and `/github/:user/:repo/` routes have very similar data requirements, specifically steps 1–4, we can use the routing infrastructure provided by `Y.App` to create reusable "middleware" which both of these routes can use. Each piece of middleware can be responsible for fetching a single data object we'll need, essentially building up the request object with everything needed to fulfill the request.
</p>

<p>
Let's see how our page-level views and route handlers work together by looking at `ContributorsApp`:
</p>

<h4>ContributorsApp</h4>

<p>
Here is our subclass of `Y.App` where we have defined our three page-level views, our app's URL-space, and our route handlers. The infrastructure provided by `Y.App` will take care of managing our page-views and dispatching to our route handlers as our users navigate through our app.
</p>

```
{{>app-contributors-js-contributors-app}}
```

<h4>Initializing the App</h4>

<p>
Finally we can create a new instance of our `ContributorsApp`, render it to the page, and be good to go!
</p>

```
{{>app-contributors-js-init}}
```


<h2>Complete Example Source</h2>

```
{{>css-yui-grids}}
{{>app-contributors-css}}
{{>app-contributors-templates}}
{{>js-yui-seed}}
{{>app-contributors-js}}
```
