├── .gitignore
├── Gulpfile.js
├── README.md
├── badge-gh.css
├── badge.js
├── dist
├── .gitkeep
├── Gulpfile.js
├── badge-gh.css
└── badge.js
├── example.html
├── example_octo.png
├── example_octogeek.png
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | node_modules
3 |
--------------------------------------------------------------------------------
/Gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var uglify = require('gulp-uglify');
3 | var minifyCss = require('gulp-minify-css');
4 |
5 | gulp.task('css', function(){
6 | return gulp.src('*.css')
7 | .pipe(minifyCss({compatibility: 'ie8'}))
8 | .pipe(gulp.dest('dist'));
9 | });
10 |
11 | gulp.task('js', function(){
12 | return gulp.src('*.js')
13 | .pipe(uglify())
14 | .pipe(gulp.dest('dist')); //the destination folder
15 | });
16 |
17 | gulp.task('default', ['js', 'css']);
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OctoBadge - Unofficial GitHub Badge
2 |
3 | ### Octo
4 |
5 | 
6 |
7 | ```
8 |
` tag, include the CSS in the `
` section.
35 |
36 | You can grab these from jsDelivr:
37 |
38 | [JS](https://cdn.jsdelivr.net/octobadge.github/0.0.1/badge.min.js)
39 | ```
40 |
41 | ```
42 |
43 | [CSS](https://cdn.jsdelivr.net/octobadge.github/0.0.1/badge.min.css)
44 | ```
45 |
46 | ```
47 |
48 | ...Then use the badge HTML:
49 |
50 | ```
51 |
)
44 | ref.parentNode.insertBefore( script, ref );
45 |
46 | // After the script is loaded (and executed), remove it
47 | script.onload = function () {
48 | this.remove();
49 | };
50 | }
51 |
52 | var stored = localStorage.getItem(url);
53 | if(stored){
54 | var now = (new Date()).getTime();
55 | var json = JSON.parse(stored);
56 |
57 | if(json.expiry > now){
58 | window[callbackMethod](json.value);
59 | } else {
60 | localStorage.removeItem(url);
61 | setLocalData = true;
62 | requestDataFromRemote();
63 | }
64 | } else {
65 | setLocalData = true;
66 | requestDataFromRemote();
67 | }
68 | };
69 |
70 | /*
71 | * Shorthand to grab an element
72 | */
73 | var el = function(s){
74 | return document.createElement(s);
75 | }
76 |
77 | /*
78 | * Set basic info from the widget
79 | */
80 | function widgetInit(widget, data){
81 | widget.className = 'github-badge';
82 | data.orientation = widget.getAttribute('orientation') || 'vertical';
83 | if(data.orientation) widget.className += ' '+data.orientation;
84 | data.badge = widget.getAttribute('badge') || 'octo';
85 | widget.className += ' '+data.badge;
86 | data.username = widget.getAttribute('user');
87 | }
88 |
89 | /*
90 | * Build the widget summary column
91 | */
92 | function widgetSummaryColumnElements(widget, data, nodes){
93 | //Create summary column
94 | nodes.summary = el('div');
95 | nodes.summary.className = 'gb-summary';
96 |
97 | var img = el('img');
98 | img.className = "user";
99 | img.width = (data.badge == 'octo' ? "50" : "100");
100 | nodes.img = img;
101 | nodes.summary.appendChild(nodes.img);
102 |
103 | var name = el('h4');
104 | nodes.name = name;
105 | nodes.summary.appendChild(nodes.name);
106 |
107 | function pwContent(contentName, iconClass){
108 | var containerName = contentName + 'Container';
109 | var c = el('p');
110 | c.className = contentName;
111 | var i = el('i');
112 | i.className=iconClass;
113 | c.appendChild(i);
114 | nodes[contentName] = el('span');
115 | c.appendChild(nodes[contentName]);
116 | nodes[containerName] = c;
117 | nodes.summary.appendChild(nodes[containerName]);
118 | }
119 |
120 | if(data.badge != 'octo') pwContent('location', 'fa fa-map-marker');
121 | pwContent('followers', 'fa fa-users');
122 | pwContent('repostotal', 'octicon octicon-repo');
123 | pwContent('stars', 'fa fa-star');
124 | if(data.badge != 'octo') pwContent('gists', 'fa fa-pencil');
125 |
126 | widget.appendChild(nodes.summary);
127 | }
128 |
129 | /*
130 | * Create detail elements
131 | */
132 | function widgetDetailElements(widget, data, nodes){
133 | if(data.badge != 'octo'){
134 | //Repos
135 | nodes.detail = el('div');
136 | nodes.detail.className = "detail";
137 |
138 | nodes.repos = {
139 | container: el('section'),
140 | title: el('h4'),
141 | listContainer: el('div')
142 | }
143 |
144 | nodes.repos.container.className = 'repos';
145 | nodes.repos.title.innerHTML = 'Popular repositories';
146 |
147 | var r_ = nodes.repos;
148 | var rc = r_.container;
149 | rc.appendChild(r_.title);
150 | rc.appendChild(r_.listContainer);
151 | nodes.detail.appendChild(rc);
152 |
153 | //Languages
154 | nodes.languages = {
155 | container: el('section'),
156 | title: el('h4'),
157 | listContainer: el('div')
158 | }
159 |
160 | nodes.languages.container.className = 'languages';
161 | nodes.languages.title.innerHTML = 'Codes in';
162 | nodes.languages.container.appendChild(nodes.languages.title);
163 | nodes.languages.container.appendChild(nodes.languages.listContainer);
164 |
165 | nodes.detail.appendChild(nodes.languages.container);
166 |
167 | widget.appendChild(nodes.detail);
168 | }
169 | }
170 |
171 | /*
172 | * Add octodex to the widget
173 | */
174 | function widgetOctodex(widget){
175 | var octodex = el('img');
176 | octodex.className = 'octodex';
177 | octodex.width = '30';
178 | octodex.src = 'data:image/png;base64,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';
179 | widget.appendChild(octodex);
180 | }
181 |
182 | /*
183 | * Load the Widget's Basic Data
184 | */
185 | function widgetDataBasic(widget, widget_data, nodes, callback){
186 | // Function to run on success
187 | window.gh_badge_basicData = function(res) {
188 | var meta = res.meta;
189 | var data = res.data;
190 |
191 | widget.addEventListener('click', function(){
192 | var a = el('a');
193 | a.target = "_blank";
194 | a.href = data.html_url;
195 | a.click();
196 | });
197 |
198 | if(nodes.img) nodes.img.src = data.avatar_url;
199 |
200 | if(nodes.name) nodes.name.innerHTML = data.name;
201 |
202 | if(nodes.location) nodes.location.innerHTML = data.location;
203 |
204 | if(nodes.followers) nodes.followers.innerHTML = data.followers + (widget_data.badge != 'octo' ? ' followers' : '');
205 |
206 | if(nodes.repostotal){
207 | nodes.repostotal.innerHTML = data.public_repos + (widget_data.badge != 'octo' ? ' public repos' : '');
208 | widget_data.repos_count = data.public_repos;
209 | }
210 |
211 | if(nodes.gists) nodes.gists.innerHTML = data.public_gists + ' gists';
212 | //if(nodes.followers) nodes.followers.innerHTML = data.followers + ' followers';
213 |
214 | var page = 0;
215 | callback(data);
216 | }
217 |
218 | // Run request
219 | loadJSONP( API_URL+'users/'+widget_data.username, 'gh_badge_basicData' );
220 | }
221 |
222 | /*
223 | * Load the Widget's Repo Data
224 | */
225 | function widgetDataRepos(widget, widget_data, nodes, basic_data){
226 | //Number of requests to make
227 | var n = Math.ceil(basic_data.public_repos/30);
228 | //Counter to check completed requests
229 | var n_ = 0;
230 |
231 | var untilDone = setInterval(function(){
232 | if(n_ == n){
233 | clearInterval(untilDone);
234 |
235 | if(widget_data.badge != 'octo'){
236 | var sorted = widget_data.repos.sort(function(a, b){
237 | if(a.stargazers_count < b.stargazers_count) return 1;
238 | if(a.stargazers_count > b.stargazers_count) return -1;
239 | return 0;
240 | });
241 |
242 | var t = sorted.slice(0, 3);
243 | t.map(function(repo){
244 | var p = el('p');
245 | var i = el('i');
246 | i.className = 'fa fa-star';
247 | p.appendChild(i);
248 | var s = el('span');
249 | s.innerHTML = repo.stargazers_count;
250 | p.appendChild(s);
251 | p.innerHTML = p.innerHTML + repo.name + ' ('+repo.language+')';
252 | nodes.repos.listContainer.appendChild(p);
253 | });
254 |
255 |
256 | var langP = el('p');
257 | var langArray = [];
258 | for(var key in widget_data.languages){
259 | if(key != 'null'){
260 | var obj = {name: key, value: widget_data.languages[key]};
261 | langArray.push(obj);
262 | }
263 | }
264 |
265 | var langSorted = langArray.sort(function(a, b){
266 | if(a.value < b.value) return 1;
267 | if(a.value > b.value) return -1;
268 | return 0;
269 | });
270 |
271 | var langString = langSorted.map(function(lang){
272 | return lang.name;
273 | }).join(', ');
274 |
275 |
276 | langP.innerHTML = langString;
277 |
278 | nodes.languages.listContainer.appendChild(langP);
279 | }
280 | }
281 | }, 1);
282 |
283 | window.gh_badge_repoData = function(res){
284 | var meta = res.meta;
285 | var data = res.data;
286 |
287 | data.map(function(repo){
288 | widget_data.stargazers = widget_data.stargazers + repo.stargazers_count;
289 | widget_data.repos.push(repo);
290 | if(widget_data.languages[repo.language]){
291 | ++widget_data.languages[repo.language];
292 | } else {
293 | widget_data.languages[repo.language] = 1;
294 | }
295 | });
296 |
297 | if(nodes.stars) nodes.stars.innerHTML = widget_data.stargazers + (widget_data.badge != 'octo' ? ' stars' : '');
298 | ++n_;
299 | }
300 |
301 | //n JSONP calls
302 | for(var i=1;i<(n+1);i++){
303 | var url = API_URL+'users/'+widget_data.username+'/repos?page='+i;
304 | loadJSONP(url, 'gh_badge_repoData');
305 | }
306 | }
307 |
308 | /*
309 | * Add the history elements
310 | */
311 | function widgetHistoryElement(widget, widget_data, nodes){
312 | if(widget_data.badge == 'octo'){
313 | nodes.history = el('div');
314 | nodes.history.className = 'history';
315 | nodes.history.id = 'github-badge-history';
316 |
317 | var day = new Date();
318 | day.setHours(0,0,0,0);
319 | day.setDate(day.getDate()-29);
320 | var DAYS_OF_HISTORY = 30;
321 |
322 | function padDigits(number, digits) {
323 | return Array(Math.max(digits - String(number).length + 1, 0)).join(0) + number;
324 | }
325 |
326 | widget_data.history = {days: {}};
327 | for(var i=0;iOcto Badge
8 | Octogeek Badge
11 |