From f896082ab54550e6cdbba23ef1a10a072e7bcdba Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sun, 3 Apr 2011 12:03:07 +0200 Subject: [PATCH 01/39] CSS Optimization --- css/resume.css | 58 +++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/css/resume.css b/css/resume.css index 46ba5ed..400612b 100644 --- a/css/resume.css +++ b/css/resume.css @@ -17,64 +17,60 @@ .msg a:hover { background: #266400; } /* //-- yui-grids style overrides -- */ -body { font-family: Georgia; color: #444; } +body { font-family: Georgia, Garamond, "Times New Roman", Times, serif; color: #444; } #inner { padding: 10px 80px; margin: 80px auto; background: #f5f5f5; border: solid #666; border-width: 8px 0 2px 0; } .yui-gf { margin-bottom: 2em; padding-bottom: 2em; border-bottom: 1px solid #ccc; } /* //-- header, body, footer -- */ -#hd { margin: 2.5em 0 3em 0; padding-bottom: 1.5em; border-bottom: 1px solid #ccc } +#hd { margin: 2.5em 0 3em 0; padding-bottom: 1.5em; border-bottom: 1px solid #ccc; } #hd h2 { text-transform: uppercase; letter-spacing: 2px; } #bd, #ft { margin-bottom: 2em; } /* //-- footer -- */ #ft { padding: 1em 0 5em 0; font-size: 92%; border-top: 1px solid #ccc; text-align: center; } -#ft p { margin-bottom: 0; text-align: center; } +#ft p { margin-bottom: 0; text-align: center; } /* //-- core typography and style -- */ #hd h1 { font-size: 48px; text-transform: uppercase; letter-spacing: 3px; } -h2 { font-size: 152% } +h2 { font-size: 152%; } h3, h4 { font-size: 122%; } h1, h2, h3, h4 { color: #333; } p { font-size: 100%; line-height: 18px; padding-right: 3em; } -a { color: #990003 } +a { color: #990003; } a:hover { text-decoration: none; } strong { font-weight: bold; } li { line-height: 24px; border-bottom: 1px solid #ccc; } -p.enlarge { font-size: 144%; padding-right: 6.5em; line-height: 24px; } -p.enlarge span { color: #000 } -.contact-info { margin-top: 7px; text-align: right; font-size: 12px; position: relative; float: left; width: 100%;} -.contact-info a { position :relative; float: left; width: 100%;} -.contact-info img {float: right; border: 1px solid #ccc; width: 150px; height: 150px; margin: -24px 0 14px;} +.enlarge { font-size: 144%; padding-right: 6.5em; line-height: 24px; } +.enlarge span { color: #000; } +.contact-info { margin-top: 7px; text-align: right; font-size: 12px; position: relative; float: left; width: 100%; } +.contact-info a { position: relative; float: left; width: 100%; } +.contact-info img { float: right; border: 1px solid #ccc; width: 150px; height: 150px; margin: -24px 0 14px; } .first h2 { font-style: italic; } -.last { border-bottom: 0 } +.last { border-bottom: 0; } /* //-- section styles -- */ -a#pdf { display: block; float: left; background: #666; color: white; padding: 6px 50px 6px 12px; margin-bottom: 6px; text-decoration: none; } -a#pdf:hover { background: #222; } +#pdf { display: block; float: left; background: #666; color: #fff; padding: 6px 50px 6px 12px; margin-bottom: 6px; text-decoration: none; } +#pdf:hover { background: #222; } .org, .job { position: relative; margin-bottom: 1em; padding-bottom: 1em; border-bottom: 1px solid #ccc; } .org a, .job a { border: none; text-decoration: none; } -.org h4, .job h4 { position: absolute; top: 0.35em; right: 0 } +.org h4, .job h4 { position: absolute; top: 0.35em; right: 0; } .org p, .job p { margin: 0.75em 0 3em 0; } .last { border: none; } -.content-languages { } -.content-languages ul { margin: 0; display: inline; float: left; position: relative; width: 30%;} -.content-languages li { margin: 3px 0; padding: 3px 0; position: relative; float: left; display-inline; } -.content-languages li span { font-size: 152%; display: block; margin-bottom: -2px; padding: 0 } -.talent { width: 32%; float: left } +.talent { width: 32%; float: left; } .talent h2 { margin-bottom: 6px; } -#srt-ttab { margin-bottom: 100px; text-align: center; } -#srt-ttab img.last { margin-top: 20px } +#srt-ttab { margin-bottom: 100px; text-align: center; } +#srt-ttab img.last { margin-top: 20px; } /* --// override to force 1/8th width grids -- */ -.yui-gf .yui-u{width:80.2%;} -.yui-gf div.first{width:12.3%;} +.yui-gf .yui-u { width: 80.2%; } +.yui-gf div.first { width: 12.3%; } -input#username { +#username { position: relative; float: left; height: 30px; @@ -83,20 +79,21 @@ input#username { -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; - font-family: Georgia; color: #444; + font-family: Georgia, Garamond, "Times New Roman", Times, serif; + color: #444; font-size: 18px; padding: 5px; } -button#gen { +#gen { position: relative; float: left; margin-left: 10px; width: 20%; height: 44px; - font-family: Georgia; color: #444; - font-size: 18px; - color: white; + font-family: Georgia, Garamond, "Times New Roman", Times, serif;; + font-size: 18px; + color: #fff; background-image: -webkit-gradient( linear, left bottom, @@ -114,8 +111,7 @@ button#gen { -moz-border-radius: 4px; border-radius: 4px; } - -button#gen:hover { +#gen:hover { cursor: pointer; } From c60d1c2d57717dc87d8748a6bf81877b82f6f44b Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sat, 9 Apr 2011 16:50:21 +0200 Subject: [PATCH 02/39] Others CSS optimization --- css/resume.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/css/resume.css b/css/resume.css index 400612b..94d9e02 100644 --- a/css/resume.css +++ b/css/resume.css @@ -12,7 +12,7 @@ .msg { padding: 10px; background: #222; position: relative; } -.msg h1 { color: #fff; } +.msg h1 { color: #fff; } .msg a { margin-left: 20px; background: #408814; color: white; padding: 4px 8px; text-decoration: none; } .msg a:hover { background: #266400; } @@ -91,7 +91,7 @@ li { line-height: 24px; border-bottom: 1px solid #ccc; } margin-left: 10px; width: 20%; height: 44px; - font-family: Georgia, Garamond, "Times New Roman", Times, serif;; + font-family: Georgia, Garamond, "Times New Roman", Times, serif; font-size: 18px; color: #fff; background-image: -webkit-gradient( From 6a64fa4e8a1ddf7b755d06dd6f81a2508927ce65 Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sun, 10 Apr 2011 17:24:47 +0200 Subject: [PATCH 03/39] Delete useless space --- js/githubresume.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/githubresume.js b/js/githubresume.js index 22a1a21..681eb2d 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -91,7 +91,7 @@ var run = function() { }; if (data.user.blog !== undefined && data.user.blog !== null) { - view.blog = addHttp + data.user.blog; + view.blog = addHttp + data.user.blog; } $.ajax({ From b3202f0f0ed5eb91ae332bc536866cf55737c693 Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sun, 10 Apr 2011 17:36:04 +0200 Subject: [PATCH 04/39] Add message if JS is disabled --- css/resume.css | 7 +++++++ index.html | 1 + 2 files changed, 8 insertions(+) diff --git a/css/resume.css b/css/resume.css index 94d9e02..ad8c231 100644 --- a/css/resume.css +++ b/css/resume.css @@ -128,3 +128,10 @@ li { line-height: 24px; border-bottom: 1px solid #ccc; } .enlarge-medium { font-size: 15px; } + +noscript { + display: block; + margin-top: 30px; + font-size: 152%; + color: #990003; +} \ No newline at end of file diff --git a/index.html b/index.html index ac1e791..d0b807c 100644 --- a/index.html +++ b/index.html @@ -13,5 +13,6 @@ + From c7a6bf6f03c773457f09c9fe3c145de0bbcf622c Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sun, 10 Apr 2011 17:41:34 +0200 Subject: [PATCH 05/39] Simplification of code to generate the blog link --- views/resume.html | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/views/resume.html b/views/resume.html index 6748f65..b1a7849 100644 --- a/views/resume.html +++ b/views/resume.html @@ -38,7 +38,7 @@ with {{repos}} public {{plural}}. I've been using github.com since {{since}} {{#blog}} - and sometimes I blog at {{blog}}. + and sometimes I blog at {{blog}}. {{/blog}}

@@ -96,9 +96,3 @@ - From 7c2590759dd9eaade6aa7f3470f9a784991d7b53 Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sun, 10 Apr 2011 18:14:23 +0200 Subject: [PATCH 06/39] Add test on blog value to prevent handling an empty string --- js/githubresume.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/githubresume.js b/js/githubresume.js index 681eb2d..9100784 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -67,7 +67,7 @@ var run = function() { since = since.getFullYear(); var addHttp = ''; - if (data.user.blog !== undefined && data.user.blog !== null) { + if (data.user.blog !== undefined && data.user.blog !== null && data.user.blog !== '') { if (data.user.blog.indexOf('http') < 0) { addHttp = 'http://'; } From 3d612dfc7c87664ccaa75de80d4019aaa4dd4568 Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sun, 10 Apr 2011 19:31:15 +0200 Subject: [PATCH 07/39] Display a dot to end the "since expression" if no blog link is specified --- views/resume.html | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/views/resume.html b/views/resume.html index b1a7849..a176f0d 100644 --- a/views/resume.html +++ b/views/resume.html @@ -36,10 +36,7 @@ based in {{location}} {{/location}} with {{repos}} public {{plural}}. - I've been using github.com since {{since}} - {{#blog}} - and sometimes I blog at {{blog}}. - {{/blog}} + I've been using github.com since {{since}}{{#blog}} and sometimes I blog at {{blog}}{{/blog}}.

From 8595bf02958961027fa525cf8005ff826ee906f3 Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sun, 10 Apr 2011 19:36:41 +0200 Subject: [PATCH 08/39] Add test on blog value to prevent handling an empty string --- js/githubresume.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/githubresume.js b/js/githubresume.js index 9100784..04ea3de 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -90,7 +90,7 @@ var run = function() { since: since }; - if (data.user.blog !== undefined && data.user.blog !== null) { + if (data.user.blog !== undefined && data.user.blog !== null && data.user.blog !== '') { view.blog = addHttp + data.user.blog; } From 8f954d4812590531f05e4c30d85738788a0aa50c Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sun, 10 Apr 2011 21:46:28 +0200 Subject: [PATCH 09/39] Add mailto links only if necessary (issue #11) --- views/resume.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/resume.html b/views/resume.html index a176f0d..f5dc630 100644 --- a/views/resume.html +++ b/views/resume.html @@ -15,7 +15,7 @@ {{#gravatar_id}} {{/gravatar_id}} -

{{email}}

+ {{#email}}

{{email}}

{{/email}} @@ -87,7 +87,7 @@
-

{{name}} — {{email}}https://github.com/{{username}}

+

{{name}} — {{#email}}{{email}} — {{/email}} https://github.com/{{username}}

From 0c809ee3ab6bff8d10e2797a01da27c62804d3a3 Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sun, 10 Apr 2011 21:53:53 +0200 Subject: [PATCH 10/39] Display number of followers (issue #9) --- js/githubresume.js | 4 +++- views/resume.html | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index 04ea3de..c59d2ba 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -85,7 +85,9 @@ var run = function() { location: data.user.location, gravatar_id: data.user.gravatar_id, repos: data.user.public_repo_count, - plural: data.user.public_repo_count > 1 ? 'repositories' : 'repository', + reposLabel: data.user.public_repo_count > 1 ? 'repositories' : 'repository', + followers: data.user.followers_count, + followersLabel: data.user.followers_count > 1 ? 'followers' : 'follower', username: username, since: since }; diff --git a/views/resume.html b/views/resume.html index f5dc630..8634e91 100644 --- a/views/resume.html +++ b/views/resume.html @@ -35,7 +35,7 @@ {{#location}} based in {{location}} {{/location}} - with {{repos}} public {{plural}}. + with {{repos}} public {{reposLabel}}{{#followers}} and {{followers}} {{followersLabel}}{{/followers}}. I've been using github.com since {{since}}{{#blog}} and sometimes I blog at {{blog}}{{/blog}}.

From 25699e1aecc3904693dfb8daad1afcb265608595 Mon Sep 17 00:00:00 2001 From: Nanda Kishore Date: Tue, 19 Apr 2011 11:34:29 +0530 Subject: [PATCH 11/39] Added README.txt with a possible usecase --- README.markdown | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 README.markdown diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..b093f97 --- /dev/null +++ b/README.markdown @@ -0,0 +1,6 @@ +####A service that creates your resume based on your GitHub repos. + +Possible Usecases: + + * Boon for all the tech-savy bosses who want to have a **quick view** of person's git/github activity, _before the interview_ + From b6c60b4c6f7e6ecfb8277980255d3545f172081a Mon Sep 17 00:00:00 2001 From: Abdulrahman Alotaiba Date: Thu, 21 Apr 2011 19:31:54 +0300 Subject: [PATCH 12/39] Fixed language not appearing for users' old repos, and fixed 'My Organizations' showing loading message for users who don't have any --- js/github.js | 27 +++++++-------------------- js/githubresume.js | 7 +------ 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/js/github.js b/js/github.js index a67bf7d..144e6f4 100644 --- a/js/github.js +++ b/js/github.js @@ -233,26 +233,7 @@ // alert(data.repositories.length); // }); gh.user.prototype.allRepos = function (callback, context) { - var repos = [], - username = this.username, - page = 1; - - function exitCallback () { - callback.call(context, { repositories: repos }); - } - - function pageLoop (data) { - if (data.repositories.length == 0) { - exitCallback(); - } else { - repos = repos.concat(data.repositories); - page += 1; - gh.repo.forUser(username, pageLoop, context, page); - } - } - - gh.repo.forUser(username, pageLoop, context, page); - + gh.repo.search('username:' + this.username, "", callback, context); return this; }; @@ -282,6 +263,11 @@ return this; } ); + + gh.user.prototype.orgs = function(callback, context) { + jsonp("user/show/" + this.username + "/organizations", callback, context); + return this; + } // Search users for `query`. gh.user.search = function (query, callback, context) { @@ -425,6 +411,7 @@ context = arguments[2]; } url += "?" + paramify(opts); + jsonp(url, callback, context); return this; }; diff --git a/js/githubresume.js b/js/githubresume.js index 22a1a21..00da513 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -54,15 +54,10 @@ var home = function() { }; var run = function() { - var gh_user = gh.user(username); var itemCount = 0, maxItems = 5, maxLanguages = 9; var res = gh_user.show(function(data) { - gh_user.allRepos(function(data) { - repos = data; - }); - var since = new Date(data.user.created_at); since = since.getFullYear(); @@ -116,7 +111,7 @@ var run = function() { if (arr[i].fork !== false) { return; } - + if (arr[i].language) { if (arr[i].language in languages) { languages[arr[i].language]++; From ac127906dd404d22110903a8e249b3834293ee3a Mon Sep 17 00:00:00 2001 From: Oscar Del Ben Date: Thu, 21 Apr 2011 21:57:06 +0200 Subject: [PATCH 13/39] update index --- views/index.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/views/index.html b/views/index.html index f92e783..5e048ab 100644 --- a/views/index.html +++ b/views/index.html @@ -54,9 +54,7 @@


This is the first version. I am planning on adding things as such as your most committed forks, most committed repositories and make the "My Popular Repositories" be built from - your complete list of repositories. The issue right now is say you have 37 repositories, this will only retrieve the first - 30 repositories that were created. I'll put a note here when this is fixed or feel free to fork the page, - make changes and send them back :-) + your complete list of repositories. Feel free to fork the page if you want to help :-)

From 0c919264bd5357c372e85531f65ef2edcaaf25f5 Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Mon, 25 Apr 2011 09:48:40 +0200 Subject: [PATCH 14/39] hCard support --- css/resume.css | 1 - views/resume.html | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/css/resume.css b/css/resume.css index 46ba5ed..aac551a 100644 --- a/css/resume.css +++ b/css/resume.css @@ -41,7 +41,6 @@ a:hover { text-decoration: none; } strong { font-weight: bold; } li { line-height: 24px; border-bottom: 1px solid #ccc; } p.enlarge { font-size: 144%; padding-right: 6.5em; line-height: 24px; } -p.enlarge span { color: #000 } .contact-info { margin-top: 7px; text-align: right; font-size: 12px; position: relative; float: left; width: 100%;} .contact-info a { position :relative; float: left; width: 100%;} .contact-info img {float: right; border: 1px solid #ccc; width: 150px; height: 150px; margin: -24px 0 14px;} diff --git a/views/resume.html b/views/resume.html index 6748f65..b716f2b 100644 --- a/views/resume.html +++ b/views/resume.html @@ -1,11 +1,11 @@
-
+
-

{{name}}

+

{{name}}

Passionate github user

@@ -13,9 +13,9 @@
{{#gravatar_id}} - + {{/gravatar_id}} -

{{email}}

+

@@ -33,12 +33,12 @@

I'm a developer {{#location}} - based in {{location}} + based in {{location}} {{/location}} with {{repos}} public {{plural}}. I've been using github.com since {{since}} {{#blog}} - and sometimes I blog at {{blog}}. + and sometimes I blog at {{blog}}. {{/blog}}

@@ -90,7 +90,7 @@
From 3fcbd8c4b1d47e9f6f9ab28f9da6d5bf387345ce Mon Sep 17 00:00:00 2001 From: "Herman J. Radtke III" Date: Thu, 12 May 2011 20:11:36 -0700 Subject: [PATCH 15/39] Make the "My Popular Repositories" be built from your complete list of repositories. Must have at least one contribution to be counted. --- js/githubresume.js | 258 ++++++++++++++++++++++++++++----------------- views/job.html | 2 +- 2 files changed, 164 insertions(+), 96 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index c99ab70..7947674 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -53,6 +53,28 @@ var home = function() { }); }; +var all_promises = function(array){ + var deferred = $.Deferred(); + var fulfilled = 0, length = array.length; + var results = []; + + if (length === 0) { + deferred.resolve(results); + } else { + array.forEach(function(promise, i){ + $.when(promise()).then(function(value) { + results[i] = value; + fulfilled++; + if(fulfilled === length){ + deferred.resolve(results); + } + }); + }); + } + + return deferred.promise(); +}; + var run = function() { var gh_user = gh.user(username); var itemCount = 0, maxItems = 5, maxLanguages = 9; @@ -106,119 +128,165 @@ var run = function() { var sorted = []; var languages = {}; + var promises = []; - repos.forEach(function(elm, i, arr) { - if (arr[i].fork !== false) { - return; - } - - if (arr[i].language) { - if (arr[i].language in languages) { - languages[arr[i].language]++; + function processRepo(repo, pos) { + if (repo.language) { + if (repo.language in languages) { + languages[repo.language]++; } else { - languages[arr[i].language] = 1; + languages[repo.language] = 1; } } - var popularity = arr[i].watchers + arr[i].forks; - sorted.push({position: i, popularity: popularity, info: arr[i]}); + var popularity = repo.watchers + repo.forks; + sorted.push({position: pos, popularity: popularity, info: repo}); + } + + repos.forEach(function(elm, i, arr) { + promises.push(function() { + return $.Deferred(function(dfd) { + // if the repo is a fork, make some jsonp calls + // and only resolve the promise after all jsonp + // calls are finished + if (arr[i].fork !== false) { + var gh_repo = gh.repo(username, arr[i].name); + gh_repo.show(function(data) { + var parent = data.repository.parent.split("/"); + var gh_fork_parent = gh.repo(parent[0], parent[1]); + gh_fork_parent.contributors(function(data) { + var contribs = data.contributors; + var found = 0; + + contribs.forEach(function(c) { + if (username == c.login) { + if (c.contributions > -1) { + processRepo(arr[i], i); + dfd.resolve(); + found = 1; + } + } + }); + + // if none of the contributors match the username + // we still need to resolve the promise + if (found !== 1) { + dfd.resolve(); + } + }); + }); + return; + } + + processRepo(arr[i], i); + dfd.resolve(); + }).promise(); + }); }); function sortByPopularity(a, b) { return b.popularity - a.popularity; }; - sorted.sort(sortByPopularity); + $.when(all_promises(promises)).then(function() { + sorted.sort(sortByPopularity); - var languageTotal = 0; - function sortLanguages(languages, limit) { - var sorted_languages = []; - for (var lang in languages) { - if (typeof(lang) !== "string") { - continue; - } - sorted_languages.push({ - name: lang, - popularity: languages[lang], - toString: function() { - return '' + this.name + ''; + var languageTotal = 0; + function sortLanguages(languages, limit) { + var sorted_languages = []; + for (var lang in languages) { + if (typeof(lang) !== "string") { + continue; } - }); - - languageTotal += languages[lang]; - - } - if (limit) { - sorted_languages = sorted_languages.slice(0, limit); - } - return sorted_languages.sort(sortByPopularity); - } - - $.ajax({ - url: 'views/job.html', - dataType: 'html', - success: function(response) { - var now = new Date().getFullYear(); - languages = sortLanguages(languages, maxLanguages); - - if (languages && languages.length > 0) { - var ul = $('
    '); - languages.forEach(function(elm, i, arr) { - x = i + 1; - var percent = parseInt((arr[i].popularity / languageTotal) * 100); - var li = $('
  • ' + arr[i].toString() + ' ('+percent+'%)
  • '); - if (x % 3 == 0 || (languages.length < 3 && i == languages.length - 1)) { - li.attr('class', 'last'); - ul.append(li); - $('#content-languages').append(ul); - ul = $('
      '); - } else { - ul.append(li); - $('#content-languages').append(ul); + sorted_languages.push({ + name: lang, + popularity: languages[lang], + toString: function() { + return '' + this.name + ''; } }); - } else { - $('#mylanguages').hide(); + + languageTotal += languages[lang]; + } - - if (sorted.length > 0) { - $('#jobs').html(''); - itemCount = 0; - sorted.forEach(function(elm, index, arr) { - if (itemCount >= maxItems) { - return; - } - - var since = new Date(arr[index].info.created_at); - since = since.getFullYear(); - - var view = { - name: arr[index].info.name, - since: since, - now: now, - language: arr[index].info.language, - description: arr[index].info.description, - username: username, - watchers: arr[index].info.watchers, - forks: arr[index].info.forks - }; - - if (itemCount == sorted.length - 1 || itemCount == maxItems - 1) { - view.last = 'last'; - } - - var template = response; - var html = Mustache.to_html(template, view); - - - $('#jobs').append($(html)); - ++itemCount; - }); - } else { - $('#jobs').html(''); - $('#jobs').append('

      I do not have any public repository. Sorry.

      '); + if (limit) { + sorted_languages = sorted_languages.slice(0, limit); } + return sorted_languages.sort(sortByPopularity); } + + $.ajax({ + url: 'views/job.html', + dataType: 'html', + success: function(response) { + var now = new Date().getFullYear(); + languages = sortLanguages(languages, maxLanguages); + + if (languages && languages.length > 0) { + var ul = $('
        '); + languages.forEach(function(elm, i, arr) { + x = i + 1; + var percent = parseInt((arr[i].popularity / languageTotal) * 100); + var li = $('
      • ' + arr[i].toString() + ' ('+percent+'%)
      • '); + if (x % 3 == 0 || (languages.length < 3 && i == languages.length - 1)) { + li.attr('class', 'last'); + ul.append(li); + $('#content-languages').append(ul); + ul = $('
          '); + } else { + ul.append(li); + $('#content-languages').append(ul); + } + }); + } else { + $('#mylanguages').hide(); + } + + if (sorted.length > 0) { + $('#jobs').html(''); + itemCount = 0; + sorted.forEach(function(elm, index, arr) { + if (itemCount >= maxItems) { + return; + } + + var relation = 'Creator & Owner'; + if (arr[index].info.fork === true) { + relation = 'Contributor'; + } + + var since = new Date(arr[index].info.created_at); + since = since.getFullYear(); + + var view = { + name: arr[index].info.name, + since: since, + now: now, + language: arr[index].info.language, + description: arr[index].info.description, + username: username, + relation: relation, + watchers: arr[index].info.watchers, + forks: arr[index].info.forks + }; + + if (itemCount == sorted.length - 1 || itemCount == maxItems - 1) { + view.last = 'last'; + } + + var template = response; + var html = Mustache.to_html(template, view); + + + $('#jobs').append($(html)); + ++itemCount; + }); + } else { + $('#jobs').html(''); + $('#jobs').append('

          I do not have any public repository. Sorry.

          '); + } + } + }); }); }); diff --git a/views/job.html b/views/job.html index 5a141ff..48dd03f 100644 --- a/views/job.html +++ b/views/job.html @@ -2,7 +2,7 @@

          {{name}}

          -

          {{#language}}{{language}} - {{/language}}Creator & Owner

          +

          {{#language}}{{language}} - {{/language}}{{relation}}

          {{since}} - {{now}}

          {{description}}.

          From 44d40757b3e8ac6eb9af1a17fbc84d2e036983c5 Mon Sep 17 00:00:00 2001 From: David Coallier Date: Mon, 16 May 2011 23:14:47 +0100 Subject: [PATCH 16/39] Revert "Make the "My Popular Repositories" be built from your complete list of repositories. Must have at least one contribution to be counted." This reverts commit 3fcbd8c4b1d47e9f6f9ab28f9da6d5bf387345ce. --- js/githubresume.js | 258 +++++++++++++++++---------------------------- views/job.html | 2 +- 2 files changed, 96 insertions(+), 164 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index 7947674..c99ab70 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -53,28 +53,6 @@ var home = function() { }); }; -var all_promises = function(array){ - var deferred = $.Deferred(); - var fulfilled = 0, length = array.length; - var results = []; - - if (length === 0) { - deferred.resolve(results); - } else { - array.forEach(function(promise, i){ - $.when(promise()).then(function(value) { - results[i] = value; - fulfilled++; - if(fulfilled === length){ - deferred.resolve(results); - } - }); - }); - } - - return deferred.promise(); -}; - var run = function() { var gh_user = gh.user(username); var itemCount = 0, maxItems = 5, maxLanguages = 9; @@ -128,165 +106,119 @@ var run = function() { var sorted = []; var languages = {}; - var promises = []; - function processRepo(repo, pos) { - if (repo.language) { - if (repo.language in languages) { - languages[repo.language]++; + repos.forEach(function(elm, i, arr) { + if (arr[i].fork !== false) { + return; + } + + if (arr[i].language) { + if (arr[i].language in languages) { + languages[arr[i].language]++; } else { - languages[repo.language] = 1; + languages[arr[i].language] = 1; } } - var popularity = repo.watchers + repo.forks; - sorted.push({position: pos, popularity: popularity, info: repo}); - } - - repos.forEach(function(elm, i, arr) { - promises.push(function() { - return $.Deferred(function(dfd) { - // if the repo is a fork, make some jsonp calls - // and only resolve the promise after all jsonp - // calls are finished - if (arr[i].fork !== false) { - var gh_repo = gh.repo(username, arr[i].name); - gh_repo.show(function(data) { - var parent = data.repository.parent.split("/"); - var gh_fork_parent = gh.repo(parent[0], parent[1]); - gh_fork_parent.contributors(function(data) { - var contribs = data.contributors; - var found = 0; - - contribs.forEach(function(c) { - if (username == c.login) { - if (c.contributions > -1) { - processRepo(arr[i], i); - dfd.resolve(); - found = 1; - } - } - }); - - // if none of the contributors match the username - // we still need to resolve the promise - if (found !== 1) { - dfd.resolve(); - } - }); - }); - return; - } - - processRepo(arr[i], i); - dfd.resolve(); - }).promise(); - }); + var popularity = arr[i].watchers + arr[i].forks; + sorted.push({position: i, popularity: popularity, info: arr[i]}); }); function sortByPopularity(a, b) { return b.popularity - a.popularity; }; - $.when(all_promises(promises)).then(function() { - sorted.sort(sortByPopularity); + sorted.sort(sortByPopularity); - var languageTotal = 0; - function sortLanguages(languages, limit) { - var sorted_languages = []; - for (var lang in languages) { - if (typeof(lang) !== "string") { - continue; + var languageTotal = 0; + function sortLanguages(languages, limit) { + var sorted_languages = []; + for (var lang in languages) { + if (typeof(lang) !== "string") { + continue; + } + sorted_languages.push({ + name: lang, + popularity: languages[lang], + toString: function() { + return '' + this.name + ''; } - sorted_languages.push({ - name: lang, - popularity: languages[lang], - toString: function() { - return '' + this.name + ''; + }); + + languageTotal += languages[lang]; + + } + if (limit) { + sorted_languages = sorted_languages.slice(0, limit); + } + return sorted_languages.sort(sortByPopularity); + } + + $.ajax({ + url: 'views/job.html', + dataType: 'html', + success: function(response) { + var now = new Date().getFullYear(); + languages = sortLanguages(languages, maxLanguages); + + if (languages && languages.length > 0) { + var ul = $('

            '); + languages.forEach(function(elm, i, arr) { + x = i + 1; + var percent = parseInt((arr[i].popularity / languageTotal) * 100); + var li = $('
          • ' + arr[i].toString() + ' ('+percent+'%)
          • '); + if (x % 3 == 0 || (languages.length < 3 && i == languages.length - 1)) { + li.attr('class', 'last'); + ul.append(li); + $('#content-languages').append(ul); + ul = $('
              '); + } else { + ul.append(li); + $('#content-languages').append(ul); } }); - - languageTotal += languages[lang]; - + } else { + $('#mylanguages').hide(); } - if (limit) { - sorted_languages = sorted_languages.slice(0, limit); + + if (sorted.length > 0) { + $('#jobs').html(''); + itemCount = 0; + sorted.forEach(function(elm, index, arr) { + if (itemCount >= maxItems) { + return; + } + + var since = new Date(arr[index].info.created_at); + since = since.getFullYear(); + + var view = { + name: arr[index].info.name, + since: since, + now: now, + language: arr[index].info.language, + description: arr[index].info.description, + username: username, + watchers: arr[index].info.watchers, + forks: arr[index].info.forks + }; + + if (itemCount == sorted.length - 1 || itemCount == maxItems - 1) { + view.last = 'last'; + } + + var template = response; + var html = Mustache.to_html(template, view); + + + $('#jobs').append($(html)); + ++itemCount; + }); + } else { + $('#jobs').html(''); + $('#jobs').append('

              I do not have any public repository. Sorry.

              '); } - return sorted_languages.sort(sortByPopularity); } - - $.ajax({ - url: 'views/job.html', - dataType: 'html', - success: function(response) { - var now = new Date().getFullYear(); - languages = sortLanguages(languages, maxLanguages); - - if (languages && languages.length > 0) { - var ul = $('
                '); - languages.forEach(function(elm, i, arr) { - x = i + 1; - var percent = parseInt((arr[i].popularity / languageTotal) * 100); - var li = $('
              • ' + arr[i].toString() + ' ('+percent+'%)
              • '); - if (x % 3 == 0 || (languages.length < 3 && i == languages.length - 1)) { - li.attr('class', 'last'); - ul.append(li); - $('#content-languages').append(ul); - ul = $('
                  '); - } else { - ul.append(li); - $('#content-languages').append(ul); - } - }); - } else { - $('#mylanguages').hide(); - } - - if (sorted.length > 0) { - $('#jobs').html(''); - itemCount = 0; - sorted.forEach(function(elm, index, arr) { - if (itemCount >= maxItems) { - return; - } - - var relation = 'Creator & Owner'; - if (arr[index].info.fork === true) { - relation = 'Contributor'; - } - - var since = new Date(arr[index].info.created_at); - since = since.getFullYear(); - - var view = { - name: arr[index].info.name, - since: since, - now: now, - language: arr[index].info.language, - description: arr[index].info.description, - username: username, - relation: relation, - watchers: arr[index].info.watchers, - forks: arr[index].info.forks - }; - - if (itemCount == sorted.length - 1 || itemCount == maxItems - 1) { - view.last = 'last'; - } - - var template = response; - var html = Mustache.to_html(template, view); - - - $('#jobs').append($(html)); - ++itemCount; - }); - } else { - $('#jobs').html(''); - $('#jobs').append('

                  I do not have any public repository. Sorry.

                  '); - } - } - }); }); }); diff --git a/views/job.html b/views/job.html index 48dd03f..5a141ff 100644 --- a/views/job.html +++ b/views/job.html @@ -2,7 +2,7 @@

                  {{name}}

                  -

                  {{#language}}{{language}} - {{/language}}{{relation}}

                  +

                  {{#language}}{{language}} - {{/language}}Creator & Owner

                  {{since}} - {{now}}

                  {{description}}.

                  From fa3b0a2d4eaeff2b7a023310a2b8e740564f5b6a Mon Sep 17 00:00:00 2001 From: Nick Novitski Date: Wed, 1 Jun 2011 10:11:02 -0700 Subject: [PATCH 17/39] pluralize no public repo message --- js/githubresume.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/githubresume.js b/js/githubresume.js index c99ab70..3d5d4dc 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -216,7 +216,7 @@ var run = function() { }); } else { $('#jobs').html(''); - $('#jobs').append('

                  I do not have any public repository. Sorry.

                  '); + $('#jobs').append('

                  I do not have any public repositories. Sorry.

                  '); } } }); From 0952a0b1134488f910f7a7c63f9f7717dacfb574 Mon Sep 17 00:00:00 2001 From: Nick Novitski Date: Wed, 1 Jun 2011 11:03:25 -0700 Subject: [PATCH 18/39] date project by last push rather than current year - #7 --- js/githubresume.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/githubresume.js b/js/githubresume.js index c99ab70..5591b11 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -158,7 +158,6 @@ var run = function() { url: 'views/job.html', dataType: 'html', success: function(response) { - var now = new Date().getFullYear(); languages = sortLanguages(languages, maxLanguages); if (languages && languages.length > 0) { @@ -191,6 +190,8 @@ var run = function() { var since = new Date(arr[index].info.created_at); since = since.getFullYear(); + var now = new Date(arr[index].info.pushed_at); + now = now.getFullYear(); var view = { name: arr[index].info.name, From d2ca7c22f81f44ff7d41ded50e09c9f247adcd21 Mon Sep 17 00:00:00 2001 From: Nick Novitski Date: Wed, 1 Jun 2011 11:11:20 -0700 Subject: [PATCH 19/39] date one-year projects by that year alone - #7 --- js/githubresume.js | 12 ++++++++---- views/job.html | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index 5591b11..f4f1746 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -190,13 +190,17 @@ var run = function() { var since = new Date(arr[index].info.created_at); since = since.getFullYear(); - var now = new Date(arr[index].info.pushed_at); - now = now.getFullYear(); + var until = new Date(arr[index].info.pushed_at); + until = until.getFullYear(); + if (since == until) { + date = since + } else { + date = since + ' - ' + until + } var view = { name: arr[index].info.name, - since: since, - now: now, + date:date, language: arr[index].info.language, description: arr[index].info.description, username: username, diff --git a/views/job.html b/views/job.html index 5a141ff..49497c0 100644 --- a/views/job.html +++ b/views/job.html @@ -3,7 +3,7 @@ {{name}}

                  {{#language}}{{language}} - {{/language}}Creator & Owner

                  -

                  {{since}} - {{now}}

                  +

                  {{date}}

                  {{description}}.

                  This repository has {{watchers}} watcher(s) and {{forks}} fork(s). From df9d5c02a777683bf8c7f3739f26b338403918a6 Mon Sep 17 00:00:00 2001 From: NumEricR <-> Date: Sat, 4 Jun 2011 21:44:00 +0200 Subject: [PATCH 20/39] =?UTF-8?q?Added=20a=20print=20stylesheet=20on=20r?= =?UTF-8?q?=C3=A9sum=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- css/print.css | 116 ++++++++++++++++++++++++++++++++++++++++++++++ index.html | 1 + views/resume.html | 6 +-- 3 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 css/print.css diff --git a/css/print.css b/css/print.css new file mode 100644 index 0000000..1f49de2 --- /dev/null +++ b/css/print.css @@ -0,0 +1,116 @@ +/* + Print stylesheet for résumés +*/ + + +/* =! Template */ + +#doc2 { + width: 100%; +} +#inner { + margin: 0 auto; + padding: 10pt; + border: 0; +} +#hd { + margin-top: 0; +} + +.enlarge { + padding-right: 0; +} + +.talent li { + border: 0; +} + +.org p, +.job p { + margin: 5pt 0 15pt; +} + +#repositories { + padding-bottom: 0; +} + +#jobs .job, +#about { + page-break-inside: avoid; +} + +#bd, +#about { + margin-bottom: 0; +} + +#ft { + padding: 5pt 0; +} + +/* --------- */ + + + +/* =! Font */ + +body { + font-size: 10pt; +} + +#hd h1 { + font-size: 28pt; +} +#hd h2 { + font-size: 14pt; +} + +#bd h2, +#profile .enlarge, +#about .enlarge { + font-size: 12pt; +} + +/* --------- */ + + + +/* =! Colors */ + +body, +h1, h2, h3, h4 { + color: #000; +} + +#inner { + background: #fff; +} + +/* --------- */ + + + +/* =! Links */ + +#profile a:after, +#repositories a:after, +#about a:after { + content: " (" attr(href) ")"; + font-style: italic; + font-size: 10pt; +} +#profile #myblog:after, +#jobs p a:after { + content: none; +} + +a { + text-decoration: none; +} + +#mylanguages a, +#jobs p a { + color: inherit; +} + +/* --------- */ \ No newline at end of file diff --git a/index.html b/index.html index d0b807c..5537897 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,7 @@ + diff --git a/views/resume.html b/views/resume.html index a176f0d..75fffe8 100644 --- a/views/resume.html +++ b/views/resume.html @@ -25,7 +25,7 @@

                  -
                  +

                  Github Profile

                  @@ -49,7 +49,7 @@
                  -
                  +

                  My Popular Repositories

                  @@ -69,7 +69,7 @@
                  -
                  +

                  About This Résumé

                  From 90cc3f41bf82570438d2e49bf99b0ba7d36f61b3 Mon Sep 17 00:00:00 2001 From: NumEricR Date: Tue, 26 Jul 2011 22:40:29 +0200 Subject: [PATCH 21/39] Fixed layout issue with repositories URL on print stylesheet --- css/print.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/css/print.css b/css/print.css index 1f49de2..c442c1b 100644 --- a/css/print.css +++ b/css/print.css @@ -34,6 +34,10 @@ padding-bottom: 0; } +#jobs h4 { + margin-top: 10pt; +} + #jobs .job, #about { page-break-inside: avoid; From 9200fd39f13a97e722d35e18acf9d0b2f625e4c1 Mon Sep 17 00:00:00 2001 From: NumEricR Date: Tue, 26 Jul 2011 23:01:49 +0200 Subject: [PATCH 22/39] Code style --- js/githubresume.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index 74d1237..2435eb5 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -81,8 +81,8 @@ var run = function() { gravatar_id: data.user.gravatar_id, repos: data.user.public_repo_count, reposLabel: data.user.public_repo_count > 1 ? 'repositories' : 'repository', - followers: data.user.followers_count, - followersLabel: data.user.followers_count > 1 ? 'followers' : 'follower', + followers: data.user.followers_count, + followersLabel: data.user.followers_count > 1 ? 'followers' : 'follower', username: username, since: since }; From 6a70e0afd661c1c1351b832eba61595db0acf541 Mon Sep 17 00:00:00 2001 From: NumEricR Date: Fri, 29 Jul 2011 21:32:23 +0200 Subject: [PATCH 23/39] Fixed code style --- js/githubresume.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index d9698e8..b2a15a6 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -192,17 +192,17 @@ var run = function() { var since = new Date(arr[index].info.created_at); since = since.getFullYear(); - var until = new Date(arr[index].info.pushed_at); - until = until.getFullYear(); - if (since == until) { - date = since - } else { - date = since + ' - ' + until - } + var until = new Date(arr[index].info.pushed_at); + until = until.getFullYear(); + if (since == until) { + date = since; + } else { + date = since + ' - ' + until; + } var view = { name: arr[index].info.name, - date:date, + date: date, language: arr[index].info.language, description: arr[index].info.description, username: username, From 7ab9ffa7006262d1ae309895f3895688fb086cff Mon Sep 17 00:00:00 2001 From: NumEricR Date: Fri, 29 Jul 2011 22:28:49 +0200 Subject: [PATCH 24/39] Fixed merge issue --- css/resume.css | 1 - 1 file changed, 1 deletion(-) diff --git a/css/resume.css b/css/resume.css index 83a2679..d4440a8 100644 --- a/css/resume.css +++ b/css/resume.css @@ -41,7 +41,6 @@ a:hover { text-decoration: none; } strong { font-weight: bold; } li { line-height: 24px; border-bottom: 1px solid #ccc; } p.enlarge { font-size: 144%; padding-right: 6.5em; line-height: 24px; } -p.enlarge span { color: #000 } .contact-info { margin-top: 7px; text-align: right; font-size: 12px; position: relative; float: left; width: 100%;} .contact-info a { position :relative; float: left; width: 100%;} .contact-info img {float: right; border: 1px solid #ccc; width: 150px; height: 150px; margin: -24px 0 14px;} From 45f0a4b6ec487a002c5e7d6ba890d8faa98ad49c Mon Sep 17 00:00:00 2001 From: NumEricR Date: Sat, 30 Jul 2011 20:26:03 +0200 Subject: [PATCH 25/39] Display organizations login if name isn't available --- js/githubresume.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index b2a15a6..217441e 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -235,7 +235,7 @@ var run = function() { var sorted = []; orgs.forEach(function(elm, i, arr) { - if (arr[i].name === undefined) { + if (arr[i].login === undefined) { return; } sorted.push({position: i, info: arr[i]}); @@ -253,9 +253,9 @@ var run = function() { if (itemCount >= maxItems) { return; } + var name = (arr[index].info.name || arr[index].info.login); var view = { - name: arr[index].info.name, - login: arr[index].info.login, + name: name, now: now }; From 319b1347ba8e77e7ac2bc1f5237e7d15ad3057cc Mon Sep 17 00:00:00 2001 From: NumEricR Date: Sat, 30 Jul 2011 21:02:01 +0200 Subject: [PATCH 26/39] JS clean up --- js/githubresume.js | 73 +++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index 217441e..9a2c56e 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -54,18 +54,18 @@ var home = function() { }; var run = function() { - var gh_user = gh.user(username); - var itemCount = 0, maxItems = 5, maxLanguages = 9; + var gh_user = gh.user(username), + itemCount = 0, + maxItems = 5, + maxLanguages = 9; var res = gh_user.show(function(data) { var since = new Date(data.user.created_at); since = since.getFullYear(); var addHttp = ''; - if (data.user.blog !== undefined && data.user.blog !== null && data.user.blog !== '') { - if (data.user.blog.indexOf('http') < 0) { - addHttp = 'http://'; - } + if (data.user.blog && data.user.blog.indexOf('http') < 0) { + addHttp = 'http://'; } var name = username; @@ -95,8 +95,8 @@ var run = function() { url: 'views/resume.html', dataType: 'html', success: function(data) { - var template = data; - var html = Mustache.to_html(template, view); + var template = data, + html = Mustache.to_html(template, view); $('#resume').html(html); document.title = name + "'s Résumé"; } @@ -104,10 +104,10 @@ var run = function() { }); gh_user.allRepos(function(data) { - var repos = data.repositories; - - var sorted = []; - var languages = {}; + var repos = data.repositories, + sorted = [], + languages = {}, + popularity; repos.forEach(function(elm, i, arr) { if (arr[i].fork !== false) { @@ -122,7 +122,7 @@ var run = function() { } } - var popularity = arr[i].watchers + arr[i].forks; + popularity = arr[i].watchers + arr[i].forks; sorted.push({position: i, popularity: popularity, info: arr[i]}); }); @@ -135,6 +135,7 @@ var run = function() { var languageTotal = 0; function sortLanguages(languages, limit) { var sorted_languages = []; + for (var lang in languages) { if (typeof(lang) !== "string") { continue; @@ -148,11 +149,12 @@ var run = function() { }); languageTotal += languages[lang]; - } + if (limit) { sorted_languages = sorted_languages.slice(0, limit); } + return sorted_languages.sort(sortByPopularity); } @@ -161,13 +163,16 @@ var run = function() { dataType: 'html', success: function(response) { languages = sortLanguages(languages, maxLanguages); - + if (languages && languages.length > 0) { - var ul = $('
                    '); + var ul = $('
                      '), + percent, li; + languages.forEach(function(elm, i, arr) { x = i + 1; - var percent = parseInt((arr[i].popularity / languageTotal) * 100); - var li = $('
                    • ' + arr[i].toString() + ' ('+percent+'%)
                    • '); + percent = parseInt((arr[i].popularity / languageTotal) * 100); + li = $('
                    • ' + arr[i].toString() + ' ('+percent+'%)
                    • '); + if (x % 3 == 0 || (languages.length < 3 && i == languages.length - 1)) { li.attr('class', 'last'); ul.append(li); @@ -185,14 +190,16 @@ var run = function() { if (sorted.length > 0) { $('#jobs').html(''); itemCount = 0; + var since, until, date, view, template, html; + sorted.forEach(function(elm, index, arr) { if (itemCount >= maxItems) { return; } - var since = new Date(arr[index].info.created_at); + since = new Date(arr[index].info.created_at); since = since.getFullYear(); - var until = new Date(arr[index].info.pushed_at); + until = new Date(arr[index].info.pushed_at); until = until.getFullYear(); if (since == until) { date = since; @@ -200,7 +207,7 @@ var run = function() { date = since + ' - ' + until; } - var view = { + view = { name: arr[index].info.name, date: date, language: arr[index].info.language, @@ -214,25 +221,22 @@ var run = function() { view.last = 'last'; } - var template = response; - var html = Mustache.to_html(template, view); - + template = response; + html = Mustache.to_html(template, view); $('#jobs').append($(html)); ++itemCount; }); } else { - $('#jobs').html(''); - $('#jobs').append('

                      I do not have any public repositories. Sorry.

                      '); + $('#jobs').html('').append('

                      I do not have any public repositories. Sorry.

                      '); } } }); }); gh_user.orgs(function(data) { - var orgs = data.organizations; - - var sorted = []; + var orgs = data.organizations, + sorted = []; orgs.forEach(function(elm, i, arr) { if (arr[i].login === undefined) { @@ -249,12 +253,15 @@ var run = function() { if (sorted.length > 0) { $('#orgs').html(''); + + var name, view, template, html; + sorted.forEach(function(elm, index, arr) { if (itemCount >= maxItems) { return; } - var name = (arr[index].info.name || arr[index].info.login); - var view = { + name = (arr[index].info.name || arr[index].info.login); + view = { name: name, now: now }; @@ -262,8 +269,8 @@ var run = function() { if (itemCount == sorted.length - 1 || itemCount == maxItems) { view.last = 'last'; } - var template = response; - var html = Mustache.to_html(template, view); + template = response; + html = Mustache.to_html(template, view); $('#orgs').append($(html)); ++itemCount; From bf90337694d75f8ed184f1913285270b1a7a1159 Mon Sep 17 00:00:00 2001 From: NumEricR Date: Thu, 25 Aug 2011 14:02:36 +0200 Subject: [PATCH 27/39] Removed unnecessary dot at the end of repositories description --- views/job.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/job.html b/views/job.html index 49497c0..bd40982 100644 --- a/views/job.html +++ b/views/job.html @@ -4,7 +4,7 @@

                      {{#language}}{{language}} - {{/language}}Creator & Owner

                      {{date}}

                      -

                      {{description}}.

                      +

                      {{description}}

                      This repository has {{watchers}} watcher(s) and {{forks}} fork(s). If you would like more information about this repository and my From dea120728a30fc89bd543e41ffbb2531bb1a3d59 Mon Sep 17 00:00:00 2001 From: Andrew Tulloch Date: Wed, 14 Dec 2011 02:08:47 +0800 Subject: [PATCH 28/39] FIX: We add proper labels for watchers and forks That is, we replace lines such as "This repository has 1 watcher(s) and 5 fork(s)" with "This repository has 1 watcher and 5 forks". --- js/githubresume.js | 4 +++- views/job.html | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index 9a2c56e..b7cf3c3 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -214,7 +214,9 @@ var run = function() { description: arr[index].info.description, username: username, watchers: arr[index].info.watchers, - forks: arr[index].info.forks + forks: arr[index].info.forks, + watchersLabel: arr[index].info.watchers > 1 ? 'watchers' : 'watcher', + forksLabel: arr[index].info.forks > 1 ? 'forks' : 'fork', }; if (itemCount == sorted.length - 1 || itemCount == maxItems - 1) { diff --git a/views/job.html b/views/job.html index bd40982..a60cd79 100644 --- a/views/job.html +++ b/views/job.html @@ -6,7 +6,7 @@

                      {{date}}

                      {{description}}

                      - This repository has {{watchers}} watcher(s) and {{forks}} fork(s). + This repository has {{watchers}} {{watchersLabel}} and {{forks}} {{forksLabel}}. If you would like more information about this repository and my contributed code, please visit the repo on From 63d834b570477387f787819065fb18a49fb98ac7 Mon Sep 17 00:00:00 2001 From: Conor McDermottroe Date: Sat, 23 Jun 2012 14:14:55 +0100 Subject: [PATCH 29/39] Switch to GitHub API V3 API V2 has been shut off since 1st June 2012. I also took the time to remove github.js since we weren't using much of it. Fixes #35 --- index.html | 1 - js/github.js | 689 --------------------------------------------- js/githubresume.js | 73 +++-- 3 files changed, 48 insertions(+), 715 deletions(-) delete mode 100644 js/github.js diff --git a/index.html b/index.html index 5537897..202f52d 100644 --- a/index.html +++ b/index.html @@ -10,7 +10,6 @@ - diff --git a/js/github.js b/js/github.js deleted file mode 100644 index 144e6f4..0000000 --- a/js/github.js +++ /dev/null @@ -1,689 +0,0 @@ -// ## Client-side Javascript API wrapper for GitHub -// -// Tries to map one-to-one with the GitHub API V2, but in a Javascripty manner. - -(function (globals) { - - // Before we implement the API methods, we will define all of our private - // variables and helper functions with one `var` statement. - var - - // The username and authentication token of the library's user. - authUsername, - authToken, - - // To save keystrokes when we make JSONP calls to the HTTP API, we will keep - // track of the root from which all V2 urls extend. - apiRoot = "https://github.com/api/v2/json/", - - // Send a JSONP request to the Github API that calls `callback` with - // the `context` argument as `this`. - // - // The `url` parameter is concatenated with the apiRoot, for the reasons - // mentioned above. The way that we are supporting non-global, anonymous - // functions is by sticking them in the globally exposed - // `gh.__jsonp_callbacks` object with a "unique" `id` that is the current - // time in milliseconds. Once the callback is called, it is deleted from the - // object to prevent memory leaks. - jsonp = function (url, callback, context) { - var id = +new Date, - script = document.createElement("script"); - - while (gh.__jsonp_callbacks[id] !== undefined) - id += Math.random(); // Avoid slight possibility of id clashes. - - gh.__jsonp_callbacks[id] = function () { - delete gh.__jsonp_callbacks[id]; - callback.apply(context, arguments); - }; - - var prefix = "?"; - if (url.indexOf("?") >= 0) - prefix = "&"; - - url += prefix + "callback=" + encodeURIComponent("gh.__jsonp_callbacks[" + id + "]"); - if (authUsername && authToken) { - url += "&login=" + authUsername + "&authToken=" + authToken; - } - script.setAttribute("src", apiRoot + url); - - document.getElementsByTagName('head')[0].appendChild(script); - }, - - // Send an HTTP POST. Unfortunately, it isn't possible to support a callback - // with the resulting data. (Please prove me wrong if you can!) - // - // This is implemented with a hack to get around the cross-domain - // restrictions on ajax calls. Basically, a form is created that will POST - // to the GitHub API URL, stuck inside an iframe so that it won't redirect - // this page, and then submitted. - post = function (url, vals) { - var - form = document.createElement("form"), - iframe = document.createElement("iframe"), - doc = iframe.contentDocument !== undefined ? - iframe.contentDocument : - iframe.contentWindow.document, - key, field; - vals = vals || {}; - - form.setAttribute("method", "post"); - form.setAttribute("action", apiRoot + url); - for (key in vals) { - if (vals.hasOwnProperty(key)) { - field = document.createElement("input"); - field.type = "hidden"; - field.value = encodeURIComponent(vals[key]); - form.appendChild(field); - } - } - - iframe.setAttribute("style", "display: none;"); - doc.body.appendChild(form); - document.body.appendChild(iframe); - form.submit(); - }, - - // This helper function will throw a TypeError if the library user is not - // properly authenticated. Otherwise, it silently returns. - authRequired = function (username) { - if (!authUsername || !authToken || authUsername !== username) { - throw new TypeError("gh: Must be authenticated to do that."); - } - }, - - // Convert an object to a url parameter string. - // - // paramify({foo:1, bar:3}) -> "foo=1&bar=3". - paramify = function (params) { - var str = "", key; - for (key in params) if (params.hasOwnProperty(key)) - str += key + "=" + params[key] + "&"; - return str.replace(/&$/, ""); - }, - - // Get around how the GH team haven't migrated all the API to version 2, and - // how gists use a different api root. - withTempApiRoot = function (tempApiRoot, fn) { - return function () { - var oldRoot = apiRoot; - apiRoot = tempApiRoot; - fn.apply(this, arguments); - apiRoot = oldRoot; - }; - }, - - // Expose the global `gh` variable, through which every API method is - // accessed, but keep a local variable around so we can reference it easily. - gh = globals.gh = {}; - - // Psuedo private home for JSONP callbacks (which are required to be global - // by the nature of JSONP, as discussed earlier). - gh.__jsonp_callbacks = {}; - - // Authenticate as a user. Does not try to validate at any point; that job - // is up to each individual method, which calls `authRequired` as needed. - gh.authenticate = function (username, token) { - authUsername = username; - authToken = token; - return this; - }; - - // ### Users - - // The constructor for user objects. Just creating an instance of a user - // doesn't fetch any data from GitHub, you need to get explicit about what - // you want to do that. - // - // var huddlej = gh.user("huddlej"); - gh.user = function (username) { - if ( !(this instanceof gh.user)) { - return new gh.user(username); - } - this.username = username; - }; - - // Show basic user info; you can get more info if you are authenticated as - // this user. - // - // gh.user("fitzgen").show(function (data) { - // console.log(data.user); - // }); - gh.user.prototype.show = function (callback, context) { - jsonp("user/show/" + this.username, callback, context); - return this; - }; - - // Update a user's info. You must be authenticated as this user for this to - // succeed. - // - // TODO: example - gh.user.prototype.update = function (params) { - authRequired(this.username); - var key, postData = { - login: authUsername, - token: authToken - }; - for (key in params) { - if (params.hasOwnProperty(key)) { - postData["values["+key+"]"] = encodeURIComponent(params[key]); - } - } - post("user/show/" + this.username, postData); - return this; - }; - - // Get a list of who this user is following. - // - // TODO: example - gh.user.prototype.following = function (callback, context) { - jsonp("user/show/" + this.username + "/following", callback, context); - }; - - // Find out what other users are following this user. - // - // TODO: example - gh.user.prototype.followers = function (callback, context) { - jsonp("user/show/" + this.username + "/followers", callback, context); - }; - - // Make this user follow some other user. You must be authenticated as this - // user for this to succeed. - // - // TODO: example - gh.user.prototype.follow = function (user) { - authRequired.call(this); - post("user/follow/" + user); - return this; - }; - - // Make this user quit following the given `user`. You must be authenticated - // as this user to succeed. - // - // TODO: example - gh.user.prototype.unfollow = function (user) { - authRequired.call(this); - post("user/unfollow/" + user); - return this; - }; - - // Get a list of repositories that this user is watching. - // - // TODO: example - gh.user.prototype.watching = function (callback, context) { - jsonp("repos/watched/" + this.username, callback, context); - return this; - }; - - // Get a list of this user's repositories, 30 per page - // - // gh.user("fitzgen").repos(function (data) { - // data.repositories.forEach(function (repo) { - // ... - // }); - // }); - gh.user.prototype.repos = function (callback, context, page) { - gh.repo.forUser(this.username, callback, context, page); - return this; - }; - - // Get a list of all repos for this user. - // - // gh.user("fitzgen").allRepos(function (data) { - // alert(data.repositories.length); - // }); - gh.user.prototype.allRepos = function (callback, context) { - gh.repo.search('username:' + this.username, "", callback, context); - return this; - }; - - // Make this user fork the repo that lives at - // http://github.com/user/repo. You must be authenticated as this user for - // this to succeed. - // - // gh.user("fitzgen").forkRepo("brianleroux", "wtfjs"); - gh.user.prototype.forkRepo = function (user, repo) { - authRequired(this.username); - post("repos/fork/" + user + "/" + repo); - return this; - }; - - // Get a list of all repos that this user can push to (including ones that - // they are just a collaborator on, and do not own). Must be authenticated - // as this user. - gh.user.prototype.pushable = function (callback, context) { - authRequired(authUsername); - jsonp("repos/pushable", callback, context); - }; - - gh.user.prototype.publicGists = withTempApiRoot( - "http://gist.github.com/api/v1/json/gists/", - function (callback, context) { - jsonp(this.username, callback, context); - return this; - } - ); - - gh.user.prototype.orgs = function(callback, context) { - jsonp("user/show/" + this.username + "/organizations", callback, context); - return this; - } - - // Search users for `query`. - gh.user.search = function (query, callback, context) { - jsonp("user/search/" + query, callback, context); - return this; - }; - - // ### Repositories - - // This is the base constructor for creating repo objects. Note that this - // won't actually hit the GitHub API until you specify what data you want, - // or what action you wish to take via a prototype method. - gh.repo = function (user, repo) { - if ( !(this instanceof gh.repo)) { - return new gh.repo(user, repo); - } - this.repo = repo; - this.user = user; - }; - - // Get basic information on this repo. - // - // gh.repo("schacon", "grit").show(function (data) { - // console.log(data.repository.description); - // }); - gh.repo.prototype.show = function (callback, context) { - jsonp("repos/show/" + this.user + "/" + this.repo, callback, context); - return this; - }; - - // Update the information for this repo. Must be authenticated as the - // repository owner. Params can include: - // - // * description - // * homepage - // * has_wiki - // * has_issues - // * has_downloads - gh.repo.prototype.update = function (params) { - authRequired(this.user); - var key, postData = { - login: authUsername, - token: authToken - }; - for (key in params) { - if (params.hasOwnProperty(key)) { - postData["values["+key+"]"] = encodeURIComponent(params[key]); - } - } - post("repos/show/" + this.user + "/" + this.repo, postData); - return this; - }; - - // Get all tags for this repo. - gh.repo.prototype.tags = function (callback, context) { - jsonp("repos/show/" + this.user + "/" + this.repo + "/tags", - callback, - context); - return this; - }; - - // Get all branches in this repo. - gh.repo.prototype.branches = function (callback, context) { - jsonp("repos/show/" + this.user + "/" + this.repo + "/branches", - callback, - context); - return this; - }; - - // Gather line count information on the language(s) used in this repo. - gh.repo.prototype.languages = function (callback, context) { - jsonp("/repos/show/" + this.user + "/" + this.repo + "/languages", - callback, - context); - return this; - }; - - // Gather data on all the forks of this repo. - gh.repo.prototype.network = function (callback, context) { - jsonp("repos/show/" + this.user + "/" + this.repo + "/network", - callback, - context); - return this; - }; - - // All users who have contributed to this repo. Pass `true` to showAnon if you - // want to see the non-github contributors. - gh.repo.prototype.contributors = function (callback, context, showAnon) { - var url = "repos/show/" + this.user + "/" + this.repo + "/contributors"; - if (showAnon) - url += "/anon"; - jsonp(url, - callback, - context); - return this; - }; - - // Get all of the collaborators for this repo. - gh.repo.prototype.collaborators = function (callback, context) { - jsonp("repos/show/" + this.user + "/" + this.repo + "/collaborators", - callback, - context); - return this; - }; - - // Add a collaborator to this project. Must be authenticated. - gh.repo.prototype.addCollaborator = function (collaborator) { - authRequired(this.user); - post("repos/collaborators/" + this.repo + "/add/" + collaborator); - return this; - }; - - // Remove a collaborator from this project. Must be authenticated. - gh.repo.prototype.removeCollaborator = function (collaborator) { - authRequired(this.user); - post("repos/collaborators/" + this.repo + "/remove/" + collaborator); - return this; - }; - - // Make this repository private. Authentication required. - gh.repo.prototype.setPrivate = function () { - authRequired(this.user); - post("repo/set/private/" + this.repo); - return this; - }; - - // Make this repository public. Authentication required. - gh.repo.prototype.setPublic = function () { - authRequired(this.user); - post("repo/set/public/" + this.repo); - return this; - }; - - // Search for repositories. `opts` may include `start_page` or `language`, - // which must be capitalized. - gh.repo.search = function (query, opts, callback, context) { - var url = "repos/search/" + query.replace(" ", "+"); - if (typeof opts === "function") { - opts = {}; - callback = arguments[1]; - context = arguments[2]; - } - url += "?" + paramify(opts); - jsonp(url, callback, context); - return this; - }; - - // Get all the repos that are owned by `user`. - gh.repo.forUser = function (user, callback, context, page) { - if (!page) - page = 1; - - jsonp("repos/show/" + user + '?page=' + page, callback, context); - return this; - }; - - // Create a repository. Must be authenticated. - gh.repo.create = function (name, opts) { - authRequired(authUsername); - opts.name = name; - post("repos/create", opts); - return this; - }; - - // Delete a repository. Must be authenticated. - gh.repo.del = function (name) { - authRequired(authUsername); - post("repos/delete/" + name); - return this; - }; - - // ### Commits - - gh.commit = function (user, repo, sha) { - if ( !(this instanceof gh.commit) ) - return new gh.commit(user, repo, sha); - this.user = user; - this.repo = repo; - this.sha = sha; - }; - - gh.commit.prototype.show = function (callback, context) { - jsonp("commits/show/" + this.user + "/" + this.repo + "/" + this.sha, - callback, - context); - return this; - }; - - // Get a list of all commits on a repos branch. - gh.commit.forBranch = function (user, repo, branch, callback, context) { - jsonp("commits/list/" + user + "/" + repo + "/" + branch, - callback, - context); - return this; - }; - - // Get a list of all commits on this path (file or dir). - gh.commit.forPath = function (user, repo, branch, path, callback, context) { - jsonp("commits/list/" + user + "/" + repo + "/" + branch + "/" + path, - callback, - context); - return this; - }; - - // ### Issues - - gh.issue = function (user, repo, number) { - if ( !(this instanceof gh.issue) ) - return new gh.commit(user, repo, number); - this.user = user; - this.repo = repo; - this.number = number; - }; - - // View this issue's info. - gh.issue.prototype.show = function (callback, context) { - jsonp("issues/show/" + this.user + "/" + this.repo + "/" + this.number, - callback, - context); - return this; - }; - - // Get a list of all comments on this issue. - gh.issue.prototype.comments = function (callback, context) { - jsonp("issues/comments/" + this.user + "/" + this.repo + "/" + this.number, - callback, - context); - return this; - }; - - // Close this issue. - gh.issue.prototype.close = function () { - authRequired(this.user); - post("issues/close/" + this.user + "/" + this.repo + "/" + this.number); - return this; - }; - - // Reopen this issue. - gh.issue.prototype.reopen = function () { - authRequired(this.user); - post("issues/reopen/" + this.user + "/" + this.repo + "/" + this.number); - return this; - }; - - // Reopen this issue. - gh.issue.prototype.update = function (title, body) { - authRequired(this.user); - post("issues/edit/" + this.user + "/" + this.repo + "/" + this.number, { - title: title, - body: body - }); - return this; - }; - - // Add `label` to this issue. If the label is not yet in the system, it will - // be created. - gh.issue.prototype.addLabel = function (label) { - post("issues/label/add/" + this.user + "/" + this.repo + "/" + label + "/" + this.number); - return this; - }; - - // Remove a label from this issue. - gh.issue.prototype.removeLabel = function (label) { - post("issues/label/remove/" + this.user + "/" + this.repo + "/" + label + "/" + this.number); - return this; - }; - - // Comment on this issue as the user that is authenticated. - gh.issue.prototype.comment = function (comment) { - authRequired(authUsername); - post("/issues/comment/" + user + "/" + repo + "/" + this.number, { - comment: comment - }); - return this; - }; - - // Get all issues' labels for the repo. - gh.issue.labels = function (user, repo) { - jsonp("issues/labels/" + user + "/" + repo, - callback, - context); - return this; - }; - - // Open an issue. Must be authenticated. - gh.issue.open = function (repo, title, body) { - authRequired(authUsername); - post("issues/open/" + authUsername + "/" + repo, { - title: title, - body: body - }); - return this; - }; - - // Search a repository's issue tracker. `state` can be "open" or "closed". - gh.issue.search = function (user, repo, state, query, callback, context) { - jsonp("/issues/search/" + user + "/" + repo + "/" + state + "/" + query, - callback, - context); - return this; - }; - - // Get a list of issues for the given repo. `state` can be "open" or - // "closed". - gh.issue.list = function (user, repo, state, callback, context) { - jsonp("issues/list/" + user + "/" + repo + "/" + state, - callback, - context); - return this; - }; - - // ### Gists - - gh.gist = function (id) { - if ( !(this instanceof gh.gist) ) { - return new gh.gist(id); - } - this.id = id; - }; - - gh.gist.prototype.show = withTempApiRoot( - "http://gist.github.com/api/v1/json/", - function (callback, context) { - jsonp(this.id, callback, cont); - return this; - } - ); - - gh.gist.prototype.file = withTempApiRoot( - "http://gist.github.com/raw/v1/json/", - function (filename, callback, context) { - jsonp(this.id + "/" + filename, callback, cont); - return this; - } - ); - - // ### Objects - - gh.object = function (user, repo) { - if (!(this instanceof gh.object)) { - return new gh.object(user, repo); - } - this.user = user; - this.repo = repo; - }; - - // Get the contents of a tree by tree SHA - gh.object.prototype.tree = function (sha, callback, context) { - jsonp("tree/show/" + this.user + "/" + this.repo + "/" + sha, - callback, - context); - return this; - }; - - // Get the data about a blob by tree SHA and path - gh.object.prototype.blob = function (path, sha, callback, context) { - jsonp("blob/show/" + this.user + "/" + this.repo + "/" + sha + "/" + path, - callback, - context); - return this; - }; - - // Get only blob meta - gh.object.prototype.blobMeta = function (path, sha, callback, context) { - jsonp("blob/show/" + this.user + "/" + this.repo + "/" + sha + "/" + path + "?meta=1", - callback, - context); - return this; - }; - - // Get list of blobs - gh.object.prototype.blobAll = function (branch, callback, context) { - jsonp("blob/all/" + this.user + "/" + this.repo + "/" + branch, - callback, - context); - return this; - }; - - // Get meta of each blob in tree - gh.object.prototype.blobFull = function (sha, callback, context) { - jsonp("blob/full/" + this.user + "/" + this.repo + "/" + sha, - callback, - context); - return this; - }; - - // ### Network - - gh.network = function(user, repo) { - if (!(this instanceof gh.network)) { - return new gh.network(user, repo); - } - this.user = user; - this.repo = repo; - }; - - gh.network.prototype.data = withTempApiRoot( - "http://github.com/", - function (nethash, start, end, callback, context) { - jsonp(this.user + "/" + this.repo + "/network_data_chunk?" - + nethash + "&" + start + "&" + end, - callback, - context); - return this; - } - ); - - gh.network.prototype.meta = withTempApiRoot( - "http://github.com/", - function (callback, context) { - jsonp(this.user + "/" + this.repo + "/network_meta", - callback, - context); - return this; - } - ); - -}(window)); - diff --git a/js/githubresume.js b/js/githubresume.js index b7cf3c3..22ad36f 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -53,42 +53,67 @@ var home = function() { }); }; +var github_user = function(username, callback) { + $.getJSON('https://api.github.com/users/' + username, callback); +} + +var github_user_repos = function(username, callback, page_number, prev_data) { + var page = (page_number ? page_number : 1), + url = 'https://api.github.com/users/' + username + '/repos', + data = (prev_data ? prev_data : []); + + if (page_number > 1) { + url += '?page=' + page_number; + } + $.getJSON(url, function(repos) { + data = data.concat(repos); + if (repos.length > 0) { + github_user_repos(username, callback, page + 1, data); + } else { + callback(data); + } + }); +} + +var github_user_orgs = function(username, callback) { + $.getJSON('https://api.github.com/users/' + username + '/orgs', callback); +} + var run = function() { - var gh_user = gh.user(username), - itemCount = 0, + var itemCount = 0, maxItems = 5, maxLanguages = 9; - var res = gh_user.show(function(data) { - var since = new Date(data.user.created_at); + var res = github_user(username, function(data) { + var since = new Date(data.created_at); since = since.getFullYear(); var addHttp = ''; - if (data.user.blog && data.user.blog.indexOf('http') < 0) { + if (data.blog && data.blog.indexOf('http') < 0) { addHttp = 'http://'; } var name = username; - if (data.user.name !== null && data.user.name !== undefined) { - name = data.user.name; + if (data.name !== null && data.name !== undefined) { + name = data.name; } var view = { name: name, - email: data.user.email, - created_at: data.user.created_at, - location: data.user.location, - gravatar_id: data.user.gravatar_id, - repos: data.user.public_repo_count, - reposLabel: data.user.public_repo_count > 1 ? 'repositories' : 'repository', - followers: data.user.followers_count, - followersLabel: data.user.followers_count > 1 ? 'followers' : 'follower', + email: data.email, + created_at: data.created_at, + location: data.location, + gravatar_id: data.gravatar_id, + repos: data.public_repos, + reposLabel: data.public_repos > 1 ? 'repositories' : 'repository', + followers: data.followers, + followersLabel: data.followers > 1 ? 'followers' : 'follower', username: username, since: since }; - if (data.user.blog !== undefined && data.user.blog !== null && data.user.blog !== '') { - view.blog = addHttp + data.user.blog; + if (data.blog !== undefined && data.blog !== null && data.blog !== '') { + view.blog = addHttp + data.blog; } $.ajax({ @@ -103,13 +128,12 @@ var run = function() { }); }); - gh_user.allRepos(function(data) { - var repos = data.repositories, - sorted = [], + github_user_repos(username, function(data) { + var sorted = [], languages = {}, popularity; - repos.forEach(function(elm, i, arr) { + data.forEach(function(elm, i, arr) { if (arr[i].fork !== false) { return; } @@ -236,11 +260,10 @@ var run = function() { }); }); - gh_user.orgs(function(data) { - var orgs = data.organizations, - sorted = []; + github_user_orgs(username, function(data) { + var sorted = []; - orgs.forEach(function(elm, i, arr) { + data.forEach(function(elm, i, arr) { if (arr[i].login === undefined) { return; } From b5671ce80358b15fea27107cbfe16365847b83ad Mon Sep 17 00:00:00 2001 From: Conor McDermottroe Date: Tue, 26 Jun 2012 01:23:30 +0100 Subject: [PATCH 30/39] JSON -> JSONP - Add missing `?callback=?` to calls to `$.getJSON` to turn them into JSONP calls to avoid same-origin lockdown. - Move from `.forEach` to `$.each` to work around intermittent breakage with `.forEach`. --- js/githubresume.js | 67 +++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/js/githubresume.js b/js/githubresume.js index 22ad36f..3216b30 100644 --- a/js/githubresume.js +++ b/js/githubresume.js @@ -54,20 +54,20 @@ var home = function() { }; var github_user = function(username, callback) { - $.getJSON('https://api.github.com/users/' + username, callback); + $.getJSON('https://api.github.com/users/' + username + '?callback=?', callback); } var github_user_repos = function(username, callback, page_number, prev_data) { var page = (page_number ? page_number : 1), - url = 'https://api.github.com/users/' + username + '/repos', + url = 'https://api.github.com/users/' + username + '/repos?callback=?', data = (prev_data ? prev_data : []); if (page_number > 1) { - url += '?page=' + page_number; + url += '&page=' + page_number; } $.getJSON(url, function(repos) { - data = data.concat(repos); - if (repos.length > 0) { + data = data.concat(repos.data); + if (repos.data.length > 0) { github_user_repos(username, callback, page + 1, data); } else { callback(data); @@ -76,7 +76,7 @@ var github_user_repos = function(username, callback, page_number, prev_data) { } var github_user_orgs = function(username, callback) { - $.getJSON('https://api.github.com/users/' + username + '/orgs', callback); + $.getJSON('https://api.github.com/users/' + username + '/orgs?callback=?', callback); } var run = function() { @@ -85,6 +85,7 @@ var run = function() { maxLanguages = 9; var res = github_user(username, function(data) { + data = data.data; var since = new Date(data.created_at); since = since.getFullYear(); @@ -133,21 +134,21 @@ var run = function() { languages = {}, popularity; - data.forEach(function(elm, i, arr) { - if (arr[i].fork !== false) { + $.each(data, function(i, repo) { + if (repo.fork !== false) { return; } - if (arr[i].language) { - if (arr[i].language in languages) { - languages[arr[i].language]++; + if (repo.language) { + if (repo.language in languages) { + languages[repo.language]++; } else { - languages[arr[i].language] = 1; + languages[repo.language] = 1; } } - popularity = arr[i].watchers + arr[i].forks; - sorted.push({position: i, popularity: popularity, info: arr[i]}); + popularity = repo.watchers + repo.forks; + sorted.push({position: i, popularity: popularity, info: repo}); }); function sortByPopularity(a, b) { @@ -192,10 +193,10 @@ var run = function() { var ul = $('

                        '), percent, li; - languages.forEach(function(elm, i, arr) { + $.each(languages, function(i, lang) { x = i + 1; - percent = parseInt((arr[i].popularity / languageTotal) * 100); - li = $('
                      • ' + arr[i].toString() + ' ('+percent+'%)
                      • '); + percent = parseInt((lang.popularity / languageTotal) * 100); + li = $('
                      • ' + lang.toString() + ' ('+percent+'%)
                      • '); if (x % 3 == 0 || (languages.length < 3 && i == languages.length - 1)) { li.attr('class', 'last'); @@ -216,14 +217,14 @@ var run = function() { itemCount = 0; var since, until, date, view, template, html; - sorted.forEach(function(elm, index, arr) { + $.each(sorted, function(index, repo) { if (itemCount >= maxItems) { return; } - since = new Date(arr[index].info.created_at); + since = new Date(repo.info.created_at); since = since.getFullYear(); - until = new Date(arr[index].info.pushed_at); + until = new Date(repo.info.pushed_at); until = until.getFullYear(); if (since == until) { date = since; @@ -232,15 +233,15 @@ var run = function() { } view = { - name: arr[index].info.name, + name: repo.info.name, date: date, - language: arr[index].info.language, - description: arr[index].info.description, + language: repo.info.language, + description: repo.info.description, username: username, - watchers: arr[index].info.watchers, - forks: arr[index].info.forks, - watchersLabel: arr[index].info.watchers > 1 ? 'watchers' : 'watcher', - forksLabel: arr[index].info.forks > 1 ? 'forks' : 'fork', + watchers: repo.info.watchers, + forks: repo.info.forks, + watchersLabel: repo.info.watchers > 1 ? 'watchers' : 'watcher', + forksLabel: repo.info.forks > 1 ? 'forks' : 'fork', }; if (itemCount == sorted.length - 1 || itemCount == maxItems - 1) { @@ -260,14 +261,14 @@ var run = function() { }); }); - github_user_orgs(username, function(data) { + github_user_orgs(username, function(response) { var sorted = []; - data.forEach(function(elm, i, arr) { - if (arr[i].login === undefined) { + $.each(response.data, function(i, org) { + if (org.login === undefined) { return; } - sorted.push({position: i, info: arr[i]}); + sorted.push({position: i, info: org}); }); $.ajax({ @@ -281,11 +282,11 @@ var run = function() { var name, view, template, html; - sorted.forEach(function(elm, index, arr) { + $.each(sorted, function(index, org) { if (itemCount >= maxItems) { return; } - name = (arr[index].info.name || arr[index].info.login); + name = (org.info.name || org.info.login); view = { name: name, now: now From be62711f5c6aa222eb3295cc395cb2d4e8465494 Mon Sep 17 00:00:00 2001 From: okor Date: Wed, 29 Aug 2012 12:45:09 -0400 Subject: [PATCH 31/39] added a config.ru for rack/local dev --- config.ru | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 config.ru diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..6ef85f9 --- /dev/null +++ b/config.ru @@ -0,0 +1,2 @@ +use Rack::Static, :urls => ["/css", "/images", "/js", "/views"], :root => "." +run lambda { |env| [200, { 'Content-Type' => 'text/html' }, File.open('index.html', File::RDONLY)] } From 9def42b332f0095ddb81448e60fb94f0ed5a08fe Mon Sep 17 00:00:00 2001 From: okor Date: Wed, 29 Aug 2012 13:09:10 -0400 Subject: [PATCH 32/39] added subtle background, added email and print links --- css/print.css | 8 ++++++-- css/resume.css | 24 ++++++++++++++++++++---- images/low_contrast_linen.png | Bin 0 -> 22749 bytes js/githubresume.js | 25 +++++++++++++++---------- views/resume.html | 10 ++++++++-- 5 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 images/low_contrast_linen.png diff --git a/css/print.css b/css/print.css index c442c1b..3745ce6 100644 --- a/css/print.css +++ b/css/print.css @@ -25,7 +25,7 @@ border: 0; } -.org p, +.org p, .job p { margin: 5pt 0 15pt; } @@ -97,7 +97,7 @@ h1, h2, h3, h4 { /* =! Links */ #profile a:after, -#repositories a:after, +#repositories a:after, #about a:after { content: " (" attr(href) ")"; font-style: italic; @@ -117,4 +117,8 @@ a { color: inherit; } +#actions { + visibility: hidden; +} + /* --------- */ \ No newline at end of file diff --git a/css/resume.css b/css/resume.css index d4440a8..f3b2975 100644 --- a/css/resume.css +++ b/css/resume.css @@ -5,7 +5,7 @@ v0.9: 5/28/09 - design and code by: thingsthatarebrown.com + design and code by: thingsthatarebrown.com (matt brown) --------------------------------------------------------------------------------- */ @@ -17,8 +17,8 @@ .msg a:hover { background: #266400; } /* //-- yui-grids style overrides -- */ -body { font-family: Georgia, Garamond, "Times New Roman", Times, serif; color: #444; } -#inner { padding: 10px 80px; margin: 80px auto; background: #f5f5f5; border: solid #666; border-width: 8px 0 2px 0; } +body { font-family: Georgia, Garamond, "Times New Roman", Times, serif; color: #444; background: url('../images/low_contrast_linen.png'); padding: 80px 0 80px 0;} +#inner { padding: 10px 80px; margin: 0 auto; background: #f5f5f5; border: solid #666; border-width: 8px 0 2px 0; box-shadow: 0 1px 3px #000; } .yui-gf { margin-bottom: 2em; padding-bottom: 2em; border-bottom: 1px solid #ccc; } /* //-- header, body, footer -- */ @@ -43,7 +43,7 @@ li { line-height: 24px; border-bottom: 1px solid #ccc; } p.enlarge { font-size: 144%; padding-right: 6.5em; line-height: 24px; } .contact-info { margin-top: 7px; text-align: right; font-size: 12px; position: relative; float: left; width: 100%;} .contact-info a { position :relative; float: left; width: 100%;} -.contact-info img {float: right; border: 1px solid #ccc; width: 150px; height: 150px; margin: -24px 0 14px;} +.contact-info img {float: right; border: 1px solid #ccc; width: 140px; height: 140px; margin: -24px 0 14px; border-radius: 3px;} .first h2 { font-style: italic; } .last { border-bottom: 0; } @@ -134,3 +134,19 @@ noscript { font-size: 152%; color: #990003; } + +#actions { + margin: 0 auto 40px auto; + width: 73.076em; +} + +#actions * { + float: right; +} + +#actions a { + color: #ccc; + text-decoration: none; + text-shadow: 0 0 5px #000; + margin-left: 1em; +} diff --git a/images/low_contrast_linen.png b/images/low_contrast_linen.png new file mode 100644 index 0000000000000000000000000000000000000000..17b491efffd1bef376c82cdd32c34db08eaa8984 GIT binary patch literal 22749 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 1 ? 'followers' : 'follower', username: username, - since: since + since: since, + resume_url: window.location }; if (data.blog !== undefined && data.blog !== null && data.blog !== '') { @@ -125,6 +126,10 @@ var run = function() { html = Mustache.to_html(template, view); $('#resume').html(html); document.title = name + "'s Résumé"; + $("#actions #print").click(function(){ + window.print(); + return false; + }); } }); }); @@ -175,11 +180,11 @@ var run = function() { languageTotal += languages[lang]; } - + if (limit) { sorted_languages = sorted_languages.slice(0, limit); } - + return sorted_languages.sort(sortByPopularity); } @@ -188,16 +193,16 @@ var run = function() { dataType: 'html', success: function(response) { languages = sortLanguages(languages, maxLanguages); - + if (languages && languages.length > 0) { var ul = $('
                          '), percent, li; - + $.each(languages, function(i, lang) { x = i + 1; percent = parseInt((lang.popularity / languageTotal) * 100); li = $('
                        • ' + lang.toString() + ' ('+percent+'%)
                        • '); - + if (x % 3 == 0 || (languages.length < 3 && i == languages.length - 1)) { li.attr('class', 'last'); ul.append(li); @@ -216,7 +221,7 @@ var run = function() { $('#jobs').html(''); itemCount = 0; var since, until, date, view, template, html; - + $.each(sorted, function(index, repo) { if (itemCount >= maxItems) { return; @@ -279,9 +284,9 @@ var run = function() { if (sorted.length > 0) { $('#orgs').html(''); - + var name, view, template, html; - + $.each(sorted, function(index, org) { if (itemCount >= maxItems) { return; @@ -322,4 +327,4 @@ if (trackerId) { })(); } -$(window).bind('error', error); +$(window).bind('error', error); \ No newline at end of file diff --git a/views/resume.html b/views/resume.html index 75dcc4a..4316082 100644 --- a/views/resume.html +++ b/views/resume.html @@ -1,4 +1,10 @@ +
                          +
                          +
                          @@ -41,12 +47,12 @@

                          -
                          +

                          Languages

                          - +
                          From 12a1aadc565287d819224894dbf29dec2f37ed56 Mon Sep 17 00:00:00 2001 From: coverband Date: Sun, 2 Sep 2012 12:55:02 -0700 Subject: [PATCH 33/39] Update views/error.html --- views/error.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/error.html b/views/error.html index 72d4306..2c9768f 100644 --- a/views/error.html +++ b/views/error.html @@ -3,7 +3,7 @@

                          - We couldn't find enough to build a résumé from. Make sure this is the good username :-). Try again with another username? + There was an issue accessing the requested profile to auto-generate a résumé. Access the user's profile directly.

                          From caf088a822902a71c9a8a36e14b9dfe01a033240 Mon Sep 17 00:00:00 2001 From: coverband Date: Sun, 2 Sep 2012 12:55:31 -0700 Subject: [PATCH 34/39] Update views/error.html --- views/error.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/error.html b/views/error.html index 2c9768f..1b03f72 100644 --- a/views/error.html +++ b/views/error.html @@ -3,7 +3,7 @@

                          - There was an issue accessing the requested profile to auto-generate a résumé. Access the user's profile directly. + There was an issue accessing the requested profile to auto-generate this résumé. Access the user's profile directly.

                          From 705d87cceb571ca516c09b9ee32805c0b9a4687d Mon Sep 17 00:00:00 2001 From: Ado Matejov Date: Mon, 3 Sep 2012 12:51:21 +0200 Subject: [PATCH 35/39] org link --- views/org.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/org.html b/views/org.html index a69c970..bacf589 100644 --- a/views/org.html +++ b/views/org.html @@ -3,7 +3,7 @@

                          {{name}}

                          Member

                          {{now}}

                          -

                          If you would like more information about this organization, please visit the organization page on Github.

                          +

                          If you would like more information about this organization, please visit the organization page on Github.

                          From 70986e3db5cfb2445b56435be36d11a1858ef583 Mon Sep 17 00:00:00 2001 From: Mohamed Mansour Date: Mon, 3 Sep 2012 18:05:47 -0700 Subject: [PATCH 36/39] Upgrade jQuery Library to support modern browsers The existing library breaks IE10 since the shim layer for jQuery 1.5 is pretty cold and has significantly changed to be a lot better. I moved to the jquery CDN since Google's CDN is really flaky and the 1.8.1 is retuning error pages on that CDN. --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 202f52d..4b3cfab 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ - + Github Résumé @@ -8,7 +8,7 @@ - + From 353dfc44b2b8500906ef429b7db4c5cce6918904 Mon Sep 17 00:00:00 2001 From: David Coallier Date: Tue, 4 Sep 2012 09:02:01 +0100 Subject: [PATCH 37/39] =?UTF-8?q?Thanks=20to=20@JamesEarlDouglas=20?= =?UTF-8?q?=E2=80=94=C2=A0PR=20#43=20=E2=80=94=20This=20makes=20sure=20to?= =?UTF-8?q?=20use=20the=20GitHub=20word=20with=20the=20proper=20format.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 6 +++--- views/index.html | 4 ++-- views/job.html | 2 +- views/org.html | 2 +- views/resume.html | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index 4b3cfab..6e52232 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,10 @@ - +/ - Github Résumé + GitHub Résumé - + diff --git a/views/index.html b/views/index.html index 5e048ab..baac670 100644 --- a/views/index.html +++ b/views/index.html @@ -1,5 +1,5 @@
                          - +

                          @@ -9,7 +9,7 @@


                          After a tweet by John Resig - I imagined that it may be nice for people to be able to generate their Github résumés. + I imagined that it may be nice for people to be able to generate their GitHub résumés.



                          diff --git a/views/job.html b/views/job.html index a60cd79..449d005 100644 --- a/views/job.html +++ b/views/job.html @@ -10,7 +10,7 @@ If you would like more information about this repository and my contributed code, please visit the repo on - Github. + GitHub.

                          diff --git a/views/org.html b/views/org.html index bacf589..8b80672 100644 --- a/views/org.html +++ b/views/org.html @@ -3,7 +3,7 @@

                          {{name}}

                          Member

                          {{now}}

                          -

                          If you would like more information about this organization, please visit the organization page on Github.

                          +

                          If you would like more information about this organization, please visit the organization page on GitHub.

                          diff --git a/views/resume.html b/views/resume.html index 75dcc4a..0cc758b 100644 --- a/views/resume.html +++ b/views/resume.html @@ -27,7 +27,7 @@
                          -

                          Github Profile

                          +

                          GitHub Profile

                          @@ -77,7 +77,7 @@

                          This résumé is generated automatically using information from my github account. The repositories are ordered by popularity based on a very simple popularity heuristic that defines the popularity of a repository - by its sum of watchers and forks. Do not hesitate to visit my github page + by its sum of watchers and forks. Do not hesitate to visit my github page for more information about my repositories and work.

                          @@ -87,7 +87,7 @@
                          -

                          {{name}} — {{#email}}{{email}} — {{/email}} https://github.com/{{username}}

                          +

                          {{name}} — {{#email}}{{email}} — {{/email}} https://github.com/{{username}}

                          From 47e5f3ac27d54ddd51a0df1ddaab14e69780cdaa Mon Sep 17 00:00:00 2001 From: David Coallier Date: Tue, 4 Sep 2012 12:04:13 +0100 Subject: [PATCH 38/39] Sometimes, humans do stupid things. This was one of them. --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 6e52232..2e1b7c6 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ -/ + GitHub Résumé From 3b265e10994d98d0eff44819ff865757fb828d9a Mon Sep 17 00:00:00 2001 From: okor Date: Tue, 4 Sep 2012 11:05:22 -0400 Subject: [PATCH 39/39] hacked around YUI insanity --- css/resume.css | 343 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 240 insertions(+), 103 deletions(-) diff --git a/css/resume.css b/css/resume.css index f3b2975..6ea05f8 100644 --- a/css/resume.css +++ b/css/resume.css @@ -1,6 +1,6 @@ /* --------------------------------------------------------------------------------- - STRIPPED DOWN RESUME TEMPLATE + STRIPPED DOWN RESUME TEMPLATE html resume v0.9: 5/28/09 @@ -10,143 +10,280 @@ --------------------------------------------------------------------------------- */ +.msg { + padding: 10px; + background: #222; + position: relative; +} -.msg { padding: 10px; background: #222; position: relative; } -.msg h1 { color: #fff; } -.msg a { margin-left: 20px; background: #408814; color: white; padding: 4px 8px; text-decoration: none; } -.msg a:hover { background: #266400; } +.msg h1 { color: #fff } + +.msg a { + margin-left: 20px; + background: #408814; + color: white; + padding: 4px 8px; + text-decoration: none; +} + +.msg a:hover { background: #266400 } + +html { + height: 100% ! important; + background: url('../images/low_contrast_linen.png'); +} /* //-- yui-grids style overrides -- */ -body { font-family: Georgia, Garamond, "Times New Roman", Times, serif; color: #444; background: url('../images/low_contrast_linen.png'); padding: 80px 0 80px 0;} -#inner { padding: 10px 80px; margin: 0 auto; background: #f5f5f5; border: solid #666; border-width: 8px 0 2px 0; box-shadow: 0 1px 3px #000; } -.yui-gf { margin-bottom: 2em; padding-bottom: 2em; border-bottom: 1px solid #ccc; } + +body { + font-family: Georgia, Garamond, "Times New Roman", Times, serif; + color: #444; +} + +#inner { + padding: 10px 80px; + margin: 0 auto; + background: #f5f5f5; + border: solid #666; + border-width: 8px 0 2px 0; + box-shadow: 0 1px 3px #000; +} + +.yui-gf { + margin-bottom: 2em; + padding-bottom: 2em; + border-bottom: 1px solid #ccc; +} + +.yui-gf div.first { width: 12.3% } + +.yui-gf .yui-u { width: 80.2% } /* //-- header, body, footer -- */ -#hd { margin: 2.5em 0 3em 0; padding-bottom: 1.5em; border-bottom: 1px solid #ccc; } -#hd h2 { text-transform: uppercase; letter-spacing: 2px; } -#bd, #ft { margin-bottom: 2em; } + +#hd { + margin: 2.5em 0 3em 0; + padding-bottom: 1.5em; + border-bottom: 1px solid #ccc; +} + +#hd h1 { + font-size: 48px; + text-transform: uppercase; + letter-spacing: 3px; +} + +#hd h2 { + text-transform: uppercase; + letter-spacing: 2px; +} + +#bd, +#ft { margin-bottom: 2em } + +#ft p { + margin-bottom: 0; + text-align: center; +} /* //-- footer -- */ -#ft { padding: 1em 0 5em 0; font-size: 92%; border-top: 1px solid #ccc; text-align: center; } -#ft p { margin-bottom: 0; text-align: center; } + +#ft { + padding: 1em 0 5em 0; + font-size: 92%; + border-top: 1px solid #ccc; + text-align: center; +} /* //-- core typography and style -- */ -#hd h1 { font-size: 48px; text-transform: uppercase; letter-spacing: 3px; } -h2 { font-size: 152%; } -h3, h4 { font-size: 122%; } -h1, h2, h3, h4 { color: #333; } -p { font-size: 100%; line-height: 18px; padding-right: 3em; } -a { color: #990003; } -a:hover { text-decoration: none; } -strong { font-weight: bold; } -li { line-height: 24px; border-bottom: 1px solid #ccc; } -p.enlarge { font-size: 144%; padding-right: 6.5em; line-height: 24px; } -.contact-info { margin-top: 7px; text-align: right; font-size: 12px; position: relative; float: left; width: 100%;} -.contact-info a { position :relative; float: left; width: 100%;} -.contact-info img {float: right; border: 1px solid #ccc; width: 140px; height: 140px; margin: -24px 0 14px; border-radius: 3px;} -.first h2 { font-style: italic; } -.last { border-bottom: 0; } +h2 { font-size: 152% } + +h3, +h4 { font-size: 122% } + +h1, +h2, +h3, +h4 { color: #333 } + +p { + font-size: 100%; + line-height: 18px; + padding-right: 3em; +} + +a { color: #990003 } + +a:hover { text-decoration: none } + +strong { font-weight: bold } + +li { + line-height: 24px; + border-bottom: 1px solid #ccc; +} + +p.enlarge { + font-size: 144%; + padding-right: 6.5em; + line-height: 24px; +} + +.contact-info { + margin-top: 7px; + text-align: right; + font-size: 12px; + position: relative; + float: left; + width: 100%; +} + +.contact-info img { + float: right; + border: 1px solid #ccc; + width: 140px; + height: 140px; + margin: -24px 0 14px; + border-radius: 3px; +} + +.contact-info a { + position : relative; + float: left; + width: 100%; +} + +.first h2 { font-style: italic } + +.last { border-bottom: 0 } /* //-- section styles -- */ -#pdf { display: block; float: left; background: #666; color: #fff; padding: 6px 50px 6px 12px; margin-bottom: 6px; text-decoration: none; } -#pdf:hover { background: #222; } +#pdf { + display: block; + float: left; + background: #666; + color: #fff; + padding: 6px 50px 6px 12px; + margin-bottom: 6px; + text-decoration: none; +} -.org, .job { position: relative; margin-bottom: 1em; padding-bottom: 1em; border-bottom: 1px solid #ccc; } -.org a, .job a { border: none; text-decoration: none; } -.org h4, .job h4 { position: absolute; top: 0.35em; right: 0; } -.org p, .job p { margin: 0.75em 0 3em 0; } +#pdf:hover { background: #222 } -.last { border: none; } -.talent { width: 32%; float: left; } -.talent h2 { margin-bottom: 6px; } +.org, +.job { + position: relative; + margin-bottom: 1em; + padding-bottom: 1em; + border-bottom: 1px solid #ccc; +} -#srt-ttab { margin-bottom: 100px; text-align: center; } -#srt-ttab img.last { margin-top: 20px; } +.org h4, +.job h4 { + position: absolute; + top: 0.35em; + right: 0; +} + +.org a, +.job a { + border: none; + text-decoration: none; +} + +.org p, +.job p { margin: 0.75em 0 3em 0 } + +.last { border: none } + +.talent { + width: 32%; + float: left; +} + +.talent h2 { margin-bottom: 6px } + +#srt-ttab { + margin-bottom: 100px; + text-align: center; +} + +#srt-ttab img.last { margin-top: 20px } /* --// override to force 1/8th width grids -- */ -.yui-gf .yui-u { width: 80.2%; } -.yui-gf div.first { width: 12.3%; } #username { - position: relative; - float: left; - height: 30px; - width: 75%; - border: 2px solid #444; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - font-family: Georgia, Garamond, "Times New Roman", Times, serif; - color: #444; - font-size: 18px; - padding: 5px; + position: relative; + float: left; + height: 30px; + width: 75%; + border: 2px solid #444; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + font-family: Georgia, Garamond, "Times New Roman", Times, serif; + color: #444; + font-size: 18px; + padding: 5px; } #gen { - position: relative; - float: left; - margin-left: 10px; - width: 20%; - height: 44px; - font-family: Georgia, Garamond, "Times New Roman", Times, serif; - font-size: 18px; - color: #fff; - background-image: -webkit-gradient( - linear, - left bottom, - left top, - color-stop(0.21, rgb(31,31,31)), - color-stop(0.61, rgb(51,51,51)) - ); - background-image: -moz-linear-gradient( - center bottom, - rgb(31,31,31) 21%, - rgb(51,51,51) 61% - ); - border: 1px solid #444; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -#gen:hover { - cursor: pointer; + position: relative; + float: left; + margin-left: 10px; + width: 20%; + height: 44px; + font-family: Georgia, Garamond, "Times New Roman", Times, serif; + font-size: 18px; + color: #fff; + background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0.21, rgb(31,31,31)), color-stop(0.61, rgb(51,51,51)) ); + background-image: -moz-linear-gradient( center bottom, rgb(31,31,31) 21%, rgb(51,51,51) 61% ); + border: 1px solid #444; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; } -.yui-gb ul { - width: 80%; -} +#gen:hover { cursor: pointer } .yui-gb { - margin-top: 10px; - margin-bottom: 10px; - padding-bottom: 10px; + margin-top: 10px; + margin-bottom: 10px; + padding-bottom: 10px; } -.enlarge-medium { - font-size: 15px; -} +.enlarge-medium { font-size: 15px } + +.yui-gb ul { width: 80% } noscript { - display: block; - margin-top: 30px; - font-size: 152%; - color: #990003; + display: block; + margin-top: 30px; + font-size: 152%; + color: #990003; } #actions { - margin: 0 auto 40px auto; - width: 73.076em; -} - -#actions * { - float: right; + padding: 30px 0 40px 0; + margin: 0 auto 0 auto; + width: 73.076em; } #actions a { - color: #ccc; - text-decoration: none; - text-shadow: 0 0 5px #000; - margin-left: 1em; + color: #ccc; + text-decoration: none; + text-shadow: 0 0 5px #000; + margin-left: 1em; } + +#actions * { float: right } + +#doc { + margin-top: 70px; + background: #f5f5f5; + padding: 25px 107px 0px 107px; +} + +#doc2 { padding-bottom: 70px } \ No newline at end of file