Created
December 9, 2011 05:00
-
-
Save ericf/1450249 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| YUI().use('app', 'handlebars', 'jsonp', function (Y) { | |
| var GithubSync, | |
| Contributor, ContributorList, Repo, RepoList, User, | |
| ContributorListView, RepoView, RepoListView, UserView, | |
| HomePageView, UserPageView, RepoPageView, | |
| ContributorsApp; | |
| // -- GithubSync --------------------------------------------------------------- | |
| GithubSync = function () {}; | |
| GithubSync.API_ORIGIN = 'https://api.github.com'; | |
| GithubSync.prototype = { | |
| githubURL: '/', | |
| buildURL: function () { | |
| return this.githubURL; | |
| }, | |
| sync: function (action, options, callback) { | |
| Y.Lang.isFunction(callback) || (callback = function () {}); | |
| if (action !== 'read') { | |
| return callback('Read-only'); | |
| } | |
| var url = this.buildURL() + '?per_page=100&callback={callback}'; | |
| Y.jsonp(GithubSync.API_ORIGIN + url, function (res) { | |
| var meta = res.meta, | |
| data = res.data; | |
| if (meta.status >= 200 && meta.status < 300) { | |
| callback(null, res); | |
| } else { | |
| callback(data.message, res); | |
| } | |
| }); | |
| }, | |
| parse: function (res) { | |
| return res.data; | |
| } | |
| }; | |
| // -- User --------------------------------------------------------------------- | |
| User = Y.Base.create('user', Y.Model, [GithubSync], { | |
| idAttribute: 'login', | |
| githubURL : '/users/{id}', | |
| buildURL: function () { | |
| return Y.Lang.sub(this.githubURL, { | |
| id: this.getAsURL('id') | |
| }); | |
| } | |
| }, { | |
| ATTRS: { | |
| login : {value: null}, | |
| name : {value: null}, | |
| html_url : {value: null}, | |
| avatar_url : {value: null}, | |
| public_repos : {value: 0}, | |
| followers : {value: 0} | |
| } | |
| }); | |
| // -- Repo --------------------------------------------------------------------- | |
| Repo = Y.Base.create('repo', Y.Model, [], { | |
| idAttribute: 'name' | |
| }, { | |
| ATTRS: { | |
| name : {value: null}, | |
| html_url : {value: null}, | |
| description: {value: null}, | |
| watchers : {value: 0}, | |
| forks : {value: 0}, | |
| language : {value: null}, | |
| owner : {value: null} | |
| } | |
| }); | |
| // -- RepoList ----------------------------------------------------------------- | |
| RepoList = Y.Base.create('repoList', Y.ModelList, [GithubSync], { | |
| model : Repo, | |
| githubURL: '/users/{user}/repos', | |
| buildURL: function () { | |
| return Y.Lang.sub(this.githubURL, { | |
| user: this.get('user').getAsURL('id') | |
| }); | |
| }, | |
| comparator: function (repo) { | |
| return -repo.get('watchers'); | |
| } | |
| }, { | |
| ATTRS: { | |
| user: {value: null} | |
| } | |
| }); | |
| // -- Contributor -------------------------------------------------------------- | |
| Contributor = Y.Base.create('contributor', User, [], {}, { | |
| ATTRS: { | |
| contributions: {value: 0} | |
| } | |
| }); | |
| // -- ContributorList ---------------------------------------------------------- | |
| ContributorList = Y.Base.create('contributorList', Y.ModelList, [GithubSync], { | |
| model : Contributor, | |
| githubURL: '/repos/{user}/{repo}/contributors', | |
| buildURL: function () { | |
| var repo = this.get('repo'); | |
| return Y.Lang.sub(this.githubURL, { | |
| user: repo.getAsURL('owner.login'), | |
| repo: repo.getAsURL('name') | |
| }); | |
| }, | |
| comparator: function (contributor) { | |
| return -contributor.get('contributions'); | |
| } | |
| }, { | |
| ATTRS: { | |
| repo: {value: null} | |
| } | |
| }); | |
| // -- HomePageView ------------------------------------------------------------- | |
| HomePageView = Y.Base.create('homePageView', Y.View, [], { | |
| template: Y.Handlebars.compile(Y.one('#t-home').getContent()), | |
| events: { | |
| 'button': { | |
| click: 'changeUser' | |
| }, | |
| 'input': { | |
| keypress: 'enter' | |
| } | |
| }, | |
| initializer: function () { | |
| this.publish('changeUser', {preventable: false}); | |
| }, | |
| render: function () { | |
| var content = this.template(this.get('model').getAttrs(['login'])); | |
| this.get('container').setContent(content); | |
| return this; | |
| }, | |
| changeUser: function () { | |
| var user = this.get('container').one('input').get('value'); | |
| if (user) { | |
| this.fire('changeUser', {user: user}); | |
| } | |
| }, | |
| enter: function (e) { | |
| // Check for 'enter' keypress. | |
| if (e.keyCode === 13) { | |
| this.changeUser(); | |
| } | |
| } | |
| }); | |
| // -- UserView ----------------------------------------------------------------- | |
| UserView = Y.Base.create('userView', Y.View, [], { | |
| template: Y.Handlebars.compile(Y.one('#t-user').getContent()), | |
| render: function () { | |
| var user = this.get('model'), | |
| content; | |
| content = this.template(user.getAttrs(['login', 'name', 'avatar_url'])); | |
| this.get('container').setContent(content); | |
| return this; | |
| } | |
| }); | |
| // -- RepoList View ------------------------------------------------------------ | |
| RepoListView = Y.Base.create('repoListView', Y.View, [], { | |
| template : Y.Handlebars.compile(Y.one('#t-repo-list').getContent()), | |
| urlTemplate: '#/github/{user}/{repo}/', | |
| render: function () { | |
| var urlTemplate = this.urlTemplate, | |
| content, reposData; | |
| reposData = this.get('modelList').map(function (repo) { | |
| var data = repo.getAttrs(['name', 'description', 'language', 'watchers', 'forks']); | |
| data.url = Y.Lang.sub(urlTemplate, { | |
| user: repo.getAsURL('owner.login'), | |
| repo: repo.getAsURL('name') | |
| }); | |
| return data; | |
| }); | |
| content = this.template({repos: reposData}); | |
| this.get('container').setContent(content); | |
| return this; | |
| } | |
| }); | |
| // -- UserPageView ------------------------------------------------------------- | |
| UserPageView = Y.Base.create('userPageView', Y.View, [], { | |
| initializer: function () { | |
| this.userView = new UserView({model: this.get('model')}); | |
| this.repoListView = new RepoListView({modelList: this.get('modelList')}); | |
| }, | |
| render: function () { | |
| var content = Y.one(Y.config.doc.createDocumentFragment()); | |
| content.append(this.userView.render().get('container')); | |
| content.append(this.repoListView.render().get('container')); | |
| this.get('container').setContent(content); | |
| return this; | |
| } | |
| }); | |
| // -- RepoView ----------------------------------------------------------------- | |
| RepoView = Y.Base.create('repoView', Y.View, [], { | |
| template : Y.Handlebars.compile(Y.one('#t-repo').getContent()), | |
| urlTemplate: '#/github/{user}/', | |
| render: function () { | |
| var repo = this.get('model'), | |
| content; | |
| content = this.template({ | |
| login : repo.get('owner.login'), | |
| avatar_url: repo.get('owner.avatar_url'), | |
| user_url : Y.Lang.sub(this.urlTemplate, {user: repo.getAsURL('owner.login')}), | |
| name : repo.get('name') | |
| }); | |
| this.get('container').setContent(content); | |
| return this; | |
| } | |
| }); | |
| // -- ContributorListView ------------------------------------------------------ | |
| ContributorListView = Y.Base.create('contributorListView', Y.View, [], { | |
| template : Y.Handlebars.compile(Y.one('#t-contributor-list').getContent()), | |
| urlTemplate: '#/github/{user}/', | |
| render: function () { | |
| var urlTemplate = this.urlTemplate, | |
| content, contributorsData; | |
| contributorsData = this.get('modelList').map(function (contributor) { | |
| var data = contributor.getAttrs(['login', 'avatar_url']); | |
| data.url = Y.Lang.sub(urlTemplate, { | |
| user: contributor.getAsURL('login') | |
| }); | |
| return data; | |
| }); | |
| content = this.template({contributors: contributorsData}); | |
| this.get('container').setContent(content); | |
| return this; | |
| } | |
| }); | |
| // -- RepoPageView ------------------------------------------------------------- | |
| RepoPageView = Y.Base.create('repoPageView', Y.View, [], { | |
| initializer: function () { | |
| this.repoView = new RepoView({model: this.get('model')}); | |
| this.contributorListView = new ContributorListView({modelList: this.get('modelList')}); | |
| }, | |
| render: function () { | |
| var content = Y.one(Y.config.doc.createDocumentFragment()); | |
| content.append(this.repoView.render().get('container')); | |
| content.append(this.contributorListView.render().get('container')); | |
| this.get('container').setContent(content); | |
| return this; | |
| } | |
| }); | |
| // -- ContributorsApp ---------------------------------------------------------- | |
| ContributorsApp = new Y.Base.create('contributorsApp', Y.App, [], { | |
| views: { | |
| homePage: { | |
| type: HomePageView | |
| }, | |
| userPage: { | |
| type : UserPageView, | |
| parent: 'homePage' | |
| }, | |
| repoPage: { | |
| type : RepoPageView, | |
| parent: 'userPage' | |
| } | |
| }, | |
| initializer: function () { | |
| this.on('homePageView:changeUser', function (e) { | |
| this.navigate('/github/' + e.user + '/'); | |
| }); | |
| }, | |
| handleUser: function (req, res, next) { | |
| var userId = req.params.user, | |
| user = this.get('user'), | |
| self = this; | |
| if (userId === user.get('id')) { | |
| req.user = user; | |
| next(); | |
| } else { | |
| user = new User({id: userId}); | |
| user.load(function () { | |
| self.set('user', user); | |
| req.user = user; | |
| next(); | |
| }); | |
| } | |
| }, | |
| handleRepos: function (req, res, next) { | |
| var user = req.user, | |
| repos = this.get('repos'); | |
| req.repos = repos; | |
| if (user === repos.get('user')) { | |
| next(); | |
| } else { | |
| repos.set('user', user).load(function () { | |
| next(); | |
| }); | |
| } | |
| }, | |
| handleRepo: function (req, res, next) { | |
| var repoId = req.params.repo; | |
| repos = req.repos, | |
| repo = repos.getById(repoId), | |
| contributors = this.get('contributors'); | |
| if (!repo) { | |
| return next('GitHub repository was not found.'); | |
| } | |
| req.repo = repo; | |
| req.contributors = contributors; | |
| if (repo === contributors.get('repo')) { | |
| next(); | |
| } else { | |
| contributors.set('repo', repo).load(function () { | |
| next(); | |
| }); | |
| } | |
| }, | |
| showHomePage: function () { | |
| this.showView('homePage', { | |
| model: this.get('user') | |
| }); | |
| }, | |
| showUserPage: function (req) { | |
| this.showView('userPage', { | |
| model : req.user, | |
| modelList: req.repos | |
| }); | |
| }, | |
| showRepoPage: function (req) { | |
| this.showView('repoPage', { | |
| model : req.repo, | |
| modelList: req.contributors | |
| }); | |
| } | |
| }, { | |
| ATTRS: { | |
| user : {value: new User()}, | |
| repos : {value: new RepoList()}, | |
| contributors: {value: new ContributorList()}, | |
| routes: { | |
| value: [ | |
| {path: '/', callback: 'showHomePage'}, | |
| {path: '/github/:user/*', callback: 'handleUser'}, | |
| {path: '/github/:user/*', callback: 'handleRepos'}, | |
| {path: '/github/:user/', callback: 'showUserPage'}, | |
| {path: '/github/:user/:repo/', callback: 'handleRepo'}, | |
| {path: '/github/:user/:repo/', callback: 'showRepoPage'} | |
| ] | |
| } | |
| } | |
| }); | |
| // -- Go-go-gadget App! -------------------------------------------------------- | |
| new ContributorsApp({ | |
| serverRouting: false, | |
| container : '.example', | |
| linkSelector : '.example a', | |
| on: { | |
| ready: function () { | |
| if (!this.hasRoute(this.getPath())) { | |
| this.replace('/'); | |
| } | |
| } | |
| } | |
| }).dispatch().render(); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <script id="t-home" type="text/x-handlebars-template"> | |
| <h2 class="no-toc">Contributors of Github Projects</h2> | |
| <div> | |
| {{#if login}} | |
| <input type="text" name="user" placeholder="Github Username" value="{{login}}" /> | |
| {{else}} | |
| <input type="text" name="user" placeholder="Github Username" value="yui" /> | |
| {{/if}} | |
| <button>Show User »</button> | |
| </div> | |
| </script> | |
| <script id="t-user" type="text/x-handlebars-template"> | |
| <h2 class="no-toc"> | |
| <img src="{{avatar_url}}" alt="{{login}}'s avatar" /> | |
| {{login}} <span>({{name}})</span> | |
| </h2> | |
| <p> | |
| <a href="#/">« Choose Github User</a> | |
| </p> | |
| </script> | |
| <script id="t-repo-list" type="text/x-handlebars-template"> | |
| <h3>Repos</h3> | |
| <ul> | |
| {{#each repos}} | |
| <li><a href="{{url}}">{{name}}</a></li> | |
| {{/each}} | |
| </ul> | |
| </script> | |
| <script id="t-repo" type="text/x-handlebars-template"> | |
| <h2 class="no-toc"> | |
| <img src="{{avatar_url}}" alt="{{login}}'s avatar" /> | |
| {{login}} / {{name}} | |
| </h2> | |
| <p> | |
| <a href="{{user_url}}">« Select Repo</a> | |
| </p> | |
| </script> | |
| <script id="t-contributor-list" type="text/x-handlebars-template"> | |
| <h3>Contributors</h3> | |
| <ul> | |
| {{#each contributors}} | |
| <li> | |
| <a href="{{url}}" title="{{login}}"> | |
| <img alt="{{login}}'s avatar" src="{{avatar_url}}" /> | |
| </a> | |
| </li> | |
| {{/each}} | |
| </ul> | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment