├── .gitignore
├── README.md
├── _includes
├── head.html
├── interactive-table.html
└── nav.html
├── _layouts
└── default.html
├── _posts
├── 2013-09-02-item-1.md
├── 2013-09-02-item-10.md
├── 2013-09-02-item-11.md
├── 2013-09-02-item-12.md
├── 2013-09-02-item-2.md
├── 2013-09-02-item-3.md
├── 2013-09-02-item-4.md
├── 2013-09-02-item-5.md
├── 2013-09-02-item-6.md
├── 2013-09-02-item-7.md
├── 2013-09-02-item-8.md
└── 2013-09-02-item-9.md
├── index.html
├── javascripts
└── list.js
├── output.json
└── params.json
/.gitignore:
--------------------------------------------------------------------------------
1 | _site/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Jekyll-DB
2 | =========
3 |
4 | An easy way to use Jekyll and Github Pages as a "database".
5 |
6 | See it in action: [http://rypan.github.io/jekyll-db](http://rypan.github.io/jekyll-db)
7 |
8 | ### Use posts as entries
9 |
10 | ```
11 | ---
12 | layout: entry
13 | company-name: AchieveMint
14 | city: San Francisco
15 | state: California
16 | employees: 100
17 |
18 | categories:
19 | - startup
20 |
21 | tags:
22 | - wellness
23 | - consumer
24 | - employer
25 | ---
26 | ```
27 |
28 | ### Output your fields in a table
29 |
30 | ```
31 |
32 | {% for post in site.posts %}
33 |
34 | {{ post.company-name }}
35 | {{ post.city }}
36 | {{ post.categories }}
37 | {{ post.tags | array_to_sentence_string }}
38 |
39 | {% endfor %}
40 |
41 | ```
42 |
43 | ### Index the appropriate fields
44 |
45 | ```
46 |
55 | ```
56 |
57 | ### Output your data as JSON
58 |
59 | ```
60 | ---
61 | layout: none
62 | ---
63 | [{% for post in site.posts %}{
64 | "company-name": "{{post.company-name}}",
65 | "city": "{{post.city}}",
66 | "state": "{{post.state}}",
67 | "employees": "{{post.employees}}",
68 | "tags": "{{ post.tags | array_to_sentence_string }}",
69 | "categories": "{{post.categories}}"
70 | }{% if forloop.rindex0 > 0 %},{% endif %}{% endfor %}]
71 | ```
72 |
73 | ### Credits
74 |
75 | All the credits go to [Jekyll](http://jekyllrb.com/), [ListJS](http://listjs.com/) + [Bootstrap](http://getbootstrap.com/). I just pulled the pieces together.
76 |
--------------------------------------------------------------------------------
/_includes/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Jekyll-DB
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/_includes/interactive-table.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Company Name
12 | City
13 | Category
14 | Tags
15 |
16 |
17 |
18 | {% for post in site.posts %}
19 |
20 | {{ post.company-name }}
21 | {{ post.city }}
22 | {{ post.categories }}
23 | {{ post.tags | array_to_sentence_string }}
24 |
25 | {% endfor %}
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/_includes/nav.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% include head.html %}
4 |
5 | {{ content }}
6 |
7 |
8 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-1.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: AchieveMint
4 | city: San Francisco
5 | state: California
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - wellness
13 | - consumer
14 | - employer
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-10.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Omada Health
4 | city: San Francisco
5 | state: California
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - diabetes
13 | - prevention
14 | - device
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-11.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Pipette
4 | city: San Francisco
5 | state: California
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - remote monitoring
13 | - device
14 | - aco
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-12.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Zipongo
4 | city: Washington
5 | state: DC
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - wellness
13 | - food
14 | - employers
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-2.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Podimetrics
4 | city: Boston
5 | state: Massachusetts
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - diabetic
13 | - device
14 | - feet
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-3.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Reify Health
4 | city: Baltimore
5 | state: Maryland
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - mobile
13 | - monitoring
14 | - aco
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-4.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Benefitter
4 | city: San Francisco
5 | state: California
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - employer
13 | - plans
14 | - aca
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-5.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Cake Health
4 | city: San Francisco
5 | state: California
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - plans
13 | - insurance
14 | - finances
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-6.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Cellscope
4 | city: Berkeley
5 | state: California
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - device
13 | - ER
14 | - children
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-7.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Cardio
4 | city: Cambridge
5 | state: Massachusetts
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - big data
13 | - sensors
14 | - devices
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-8.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: Eligible
4 | city: Mountain View
5 | state: California
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - eligibility
13 | - api
14 | - plans
15 | ---
16 |
--------------------------------------------------------------------------------
/_posts/2013-09-02-item-9.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: entry
3 | company-name: LabDoor
4 | city: Chicago
5 | state: Illinois
6 | employees: 100
7 |
8 | categories:
9 | - startup
10 |
11 | tags:
12 | - consumer
13 | - safety
14 | - lab
15 | ---
16 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Jekyll-DB
11 |
An easy way to use Jekyll and Github Pages as a "database". Items are just posts . Type to search. Click on row headers to sort. See a JSON representation of the data below.
12 |
13 |
14 |
15 | {% include interactive-table.html %}
16 |
17 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/javascripts/list.js:
--------------------------------------------------------------------------------
1 | /*
2 | ListJS Beta 0.2.0
3 | By Jonny Strömberg (www.jonnystromberg.com, www.listjs.com)
4 |
5 | OBS. The API is not frozen. It MAY change!
6 |
7 | License (MIT)
8 |
9 | Copyright (c) 2011 Jonny Strömberg http://jonnystromberg.com
10 |
11 | Permission is hereby granted, free of charge, to any person
12 | obtaining a copy of this software and associated documentation
13 | files (the "Software"), to deal in the Software without restriction,
14 | including without limitation the rights to use, copy, modify, merge,
15 | publish, distribute, sublicense, and/or sell copies of the Software,
16 | and to permit persons to whom the Software is furnished to do so,
17 | subject to the following conditions:
18 |
19 | The above copyright notice and this permission notice shall be
20 | included in all copies or substantial portions of the Software.
21 |
22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
24 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29 | OTHER DEALINGS IN THE SOFTWARE.
30 | */
31 | (function( window, undefined ) {
32 | "use strict";
33 | var document = window.document,
34 | h;
35 |
36 | var List = function(id, options, values) {
37 | var self = this,
38 | templater,
39 | init,
40 | initialItems,
41 | Item,
42 | Templater,
43 | sortButtons,
44 | events = {
45 | 'updated': []
46 | };
47 | this.listContainer = (typeof(id) == 'string') ? document.getElementById(id) : id;
48 | // Check if the container exists. If not return instead of breaking the javascript
49 | if (!this.listContainer)
50 | return;
51 |
52 | this.items = [];
53 | this.visibleItems = []; // These are the items currently visible
54 | this.matchingItems = []; // These are the items currently matching filters and search, regadlessof visible count
55 | this.searched = false;
56 | this.filtered = false;
57 |
58 | this.list = null;
59 | this.templateEngines = {};
60 |
61 | this.page = options.page || 200;
62 | this.i = options.i || 1;
63 |
64 | init = {
65 | start: function(values, options) {
66 | options.plugins = options.plugins || {};
67 | this.classes(options);
68 | templater = new Templater(self, options);
69 | this.callbacks(options);
70 | this.items.start(values, options);
71 | self.update();
72 | this.plugins(options.plugins);
73 | },
74 | classes: function(options) {
75 | options.listClass = options.listClass || 'list';
76 | options.searchClass = options.searchClass || 'search';
77 | options.sortClass = options.sortClass || 'sort';
78 | },
79 | callbacks: function(options) {
80 | self.list = h.getByClass(options.listClass, self.listContainer, true);
81 | h.addEvent(h.getByClass(options.searchClass, self.listContainer), 'keyup', self.search);
82 | sortButtons = h.getByClass(options.sortClass, self.listContainer);
83 | h.addEvent(sortButtons, 'click', self.sort);
84 | },
85 | items: {
86 | start: function(values, options) {
87 | if (options.valueNames) {
88 | var itemsToIndex = this.get(),
89 | valueNames = options.valueNames;
90 | if (options.indexAsync) {
91 | this.indexAsync(itemsToIndex, valueNames);
92 | } else {
93 | this.index(itemsToIndex, valueNames);
94 | }
95 | }
96 | if (values !== undefined) {
97 | self.add(values);
98 | }
99 | },
100 | get: function() {
101 | // return h.getByClass('item', self.list);
102 | var nodes = self.list.childNodes,
103 | items = [];
104 | for (var i = 0, il = nodes.length; i < il; i++) {
105 | // Only textnodes have a data attribute
106 | if (nodes[i].data === undefined) {
107 | items.push(nodes[i]);
108 | }
109 | }
110 | return items;
111 | },
112 | index: function(itemElements, valueNames) {
113 | for (var i = 0, il = itemElements.length; i < il; i++) {
114 | self.items.push(new Item(valueNames, itemElements[i]));
115 | }
116 | },
117 | indexAsync: function(itemElements, valueNames) {
118 | var itemsToIndex = itemElements.splice(0, 100); // TODO: If < 100 items, what happens in IE etc?
119 | this.index(itemsToIndex, valueNames);
120 | if (itemElements.length > 0) {
121 | setTimeout(function() {
122 | init.items.indexAsync(itemElements, valueNames);
123 | },
124 | 10);
125 | } else {
126 | self.update();
127 | // TODO: Add indexed callback
128 | }
129 | }
130 | },
131 | plugins: function(plugins) {
132 | var locals = {
133 | templater: templater,
134 | init: init,
135 | initialItems: initialItems,
136 | Item: Item,
137 | Templater: Templater,
138 | sortButtons: sortButtons,
139 | events: events,
140 | reset: reset
141 | };
142 | for (var i = 0; i < plugins.length; i++) {
143 | plugins[i][1] = plugins[i][1] || {};
144 | var pluginName = plugins[i][1].name || plugins[i][0];
145 | self[pluginName] = self.plugins[plugins[i][0]].call(self, locals, plugins[i][1]);
146 | }
147 | }
148 | };
149 |
150 |
151 | /*
152 | * Add object to list
153 | */
154 | this.add = function(values, callback) {
155 | if (callback) {
156 | addAsync(values, callback);
157 | }
158 | var added = [],
159 | notCreate = false;
160 | if (values[0] === undefined){
161 | values = [values];
162 | }
163 | for (var i = 0, il = values.length; i < il; i++) {
164 | var item = null;
165 | if (values[i] instanceof Item) {
166 | item = values[i];
167 | item.reload();
168 | } else {
169 | notCreate = (self.items.length > self.page) ? true : false;
170 | item = new Item(values[i], undefined, notCreate);
171 | }
172 | self.items.push(item);
173 | added.push(item);
174 | }
175 | self.update();
176 | return added;
177 | };
178 |
179 | /*
180 | * Adds items asynchronous to the list, good for adding huge amount of
181 | * data. Defaults to add 100 items a time
182 | */
183 | var addAsync = function(values, callback, items) {
184 | var valuesToAdd = values.splice(0, 100);
185 | items = items || [];
186 | items = items.concat(self.add(valuesToAdd));
187 | if (values.length > 0) {
188 | setTimeout(function() {
189 | addAsync(values, callback, items);
190 | }, 10);
191 | } else {
192 | self.update();
193 | callback(items);
194 | }
195 | };
196 |
197 | this.show = function(i, page) {
198 | this.i = i;
199 | this.page = page;
200 | self.update();
201 | };
202 |
203 | /* Removes object from list.
204 | * Loops through the list and removes objects where
205 | * property "valuename" === value
206 | */
207 | this.remove = function(valueName, value, options) {
208 | var found = 0;
209 | for (var i = 0, il = self.items.length; i < il; i++) {
210 | if (self.items[i].values()[valueName] == value) {
211 | templater.remove(self.items[i], options);
212 | self.items.splice(i,1);
213 | il--;
214 | found++;
215 | }
216 | }
217 | self.update();
218 | return found;
219 | };
220 |
221 | /* Gets the objects in the list which
222 | * property "valueName" === value
223 | */
224 | this.get = function(valueName, value) {
225 | var matchedItems = [];
226 | for (var i = 0, il = self.items.length; i < il; i++) {
227 | var item = self.items[i];
228 | if (item.values()[valueName] == value) {
229 | matchedItems.push(item);
230 | }
231 | }
232 | if (matchedItems.length == 0) {
233 | return null;
234 | } else if (matchedItems.length == 1) {
235 | return matchedItems[0];
236 | } else {
237 | return matchedItems;
238 | }
239 | };
240 |
241 | /* Sorts the list.
242 | * @valueOrEvent Either a JavaScript event object or a valueName
243 | * @sortFunction (optional) Define if natural sorting does not fullfill your needs
244 | */
245 | this.sort = function(valueName, options) {
246 | var length = self.items.length,
247 | value = null,
248 | target = valueName.target || valueName.srcElement, /* IE have srcElement */
249 | sorting = '',
250 | isAsc = false,
251 | asc = 'asc',
252 | desc = 'desc',
253 | options = options || {};
254 |
255 | if (target === undefined) {
256 | value = valueName;
257 | isAsc = options.asc || false;
258 | } else {
259 | value = h.getAttribute(target, 'data-sort');
260 | isAsc = h.hasClass(target, asc) ? false : true;
261 | }
262 | for (var i = 0, il = sortButtons.length; i < il; i++) {
263 | h.removeClass(sortButtons[i], asc);
264 | h.removeClass(sortButtons[i], desc);
265 | }
266 | if (isAsc) {
267 | if (target !== undefined) {
268 | h.addClass(target, asc);
269 | }
270 | isAsc = true;
271 | } else {
272 | if (target !== undefined) {
273 | h.addClass(target, desc);
274 | }
275 | isAsc = false;
276 | }
277 |
278 | if (options.sortFunction) {
279 | options.sortFunction = options.sortFunction;
280 | } else {
281 | options.sortFunction = function(a, b) {
282 | return h.sorter.alphanum(a.values()[value].toLowerCase(), b.values()[value].toLowerCase(), isAsc);
283 | };
284 | }
285 | self.items.sort(options.sortFunction);
286 | self.update();
287 | };
288 |
289 | /*
290 | * Searches the list after values with content "searchStringOrEvent".
291 | * The columns parameter defines if all values should be included in the search,
292 | * defaults to undefined which means "all".
293 | */
294 | this.search = function(searchString, columns) {
295 | self.i = 1; // Reset paging
296 | var matching = [],
297 | found,
298 | item,
299 | text,
300 | values,
301 | is,
302 | columns = (columns === undefined) ? self.items[0].values() : columns,
303 | searchString = (searchString === undefined) ? "" : searchString,
304 | target = searchString.target || searchString.srcElement; /* IE have srcElement */
305 |
306 | searchString = (target === undefined) ? (""+searchString).toLowerCase() : ""+target.value.toLowerCase();
307 | is = self.items;
308 | // Escape regular expression characters
309 | searchString = searchString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
310 |
311 | templater.clear();
312 | if (searchString === "" ) {
313 | reset.search();
314 | self.searched = false;
315 | self.update();
316 | } else {
317 | self.searched = true;
318 |
319 | for (var k = 0, kl = is.length; k < kl; k++) {
320 | found = false;
321 | item = is[k];
322 | values = item.values();
323 |
324 | for(var j in columns) {
325 | if(values.hasOwnProperty(j) && columns[j] !== null) {
326 | text = (values[j] != null) ? values[j].toString().toLowerCase() : "";
327 | if ((searchString !== "") && (text.search(searchString) > -1)) {
328 | found = true;
329 | }
330 | }
331 | }
332 | if (found) {
333 | item.found = true;
334 | matching.push(item);
335 | } else {
336 | item.found = false;
337 | }
338 | }
339 | self.update();
340 | }
341 | return self.visibleItems;
342 | };
343 |
344 | /*
345 | * Filters the list. If filterFunction() returns False hides the Item.
346 | * if filterFunction == false are the filter removed
347 | */
348 | this.filter = function(filterFunction) {
349 | self.i = 1; // Reset paging
350 | reset.filter();
351 | if (filterFunction === undefined) {
352 | self.filtered = false;
353 | } else {
354 | self.filtered = true;
355 | var is = self.items;
356 | for (var i = 0, il = is.length; i < il; i++) {
357 | var item = is[i];
358 | if (filterFunction(item)) {
359 | item.filtered = true;
360 | } else {
361 | item.filtered = false;
362 | }
363 | }
364 | }
365 | self.update();
366 | return self.visibleItems;
367 | };
368 |
369 | /*
370 | * Get size of the list
371 | */
372 | this.size = function() {
373 | return self.items.length;
374 | };
375 |
376 | /*
377 | * Removes all items from the list
378 | */
379 | this.clear = function() {
380 | templater.clear();
381 | self.items = [];
382 | };
383 |
384 | this.on = function(event, callback) {
385 | events[event].push(callback);
386 | };
387 |
388 | var trigger = function(event) {
389 | var i = events[event].length;
390 | while(i--) {
391 | events[event][i]();
392 | }
393 | };
394 |
395 | var reset = {
396 | filter: function() {
397 | var is = self.items,
398 | il = is.length;
399 | while (il--) {
400 | is[il].filtered = false;
401 | }
402 | },
403 | search: function() {
404 | var is = self.items,
405 | il = is.length;
406 | while (il--) {
407 | is[il].found = false;
408 | }
409 | }
410 | };
411 |
412 |
413 | this.update = function() {
414 | var is = self.items,
415 | il = is.length;
416 |
417 | self.visibleItems = [];
418 | self.matchingItems = [];
419 | templater.clear();
420 | for (var i = 0; i < il; i++) {
421 | if (is[i].matching() && ((self.matchingItems.length+1) >= self.i && self.visibleItems.length < self.page)) {
422 | is[i].show();
423 | self.visibleItems.push(is[i]);
424 | self.matchingItems.push(is[i]);
425 | } else if (is[i].matching()) {
426 | self.matchingItems.push(is[i]);
427 | is[i].hide();
428 | } else {
429 | is[i].hide();
430 | }
431 | }
432 | trigger('updated');
433 | };
434 |
435 | Item = function(initValues, element, notCreate) {
436 | var item = this,
437 | values = {};
438 |
439 | this.found = false; // Show if list.searched == true and this.found == true
440 | this.filtered = false;// Show if list.filtered == true and this.filtered == true
441 |
442 | var init = function(initValues, element, notCreate) {
443 | if (element === undefined) {
444 | if (notCreate) {
445 | item.values(initValues, notCreate);
446 | } else {
447 | item.values(initValues);
448 | }
449 | } else {
450 | item.elm = element;
451 | var values = templater.get(item, initValues);
452 | item.values(values);
453 | }
454 | };
455 | this.values = function(newValues, notCreate) {
456 | if (newValues !== undefined) {
457 | for(var name in newValues) {
458 | values[name] = newValues[name];
459 | }
460 | if (notCreate !== true) {
461 | templater.set(item, item.values());
462 | }
463 | } else {
464 | return values;
465 | }
466 | };
467 | this.show = function() {
468 | templater.show(item);
469 | };
470 | this.hide = function() {
471 | templater.hide(item);
472 | };
473 | this.matching = function() {
474 | return (
475 | (self.filtered && self.searched && item.found && item.filtered) ||
476 | (self.filtered && !self.searched && item.filtered) ||
477 | (!self.filtered && self.searched && item.found) ||
478 | (!self.filtered && !self.searched)
479 | );
480 | };
481 | this.visible = function() {
482 | return (item.elm.parentNode) ? true : false;
483 | };
484 | init(initValues, element, notCreate);
485 | };
486 |
487 | /* Templater with different kinds of template engines.
488 | * All engines have these methods
489 | * - reload(item)
490 | * - remove(item)
491 | */
492 | Templater = function(list, settings) {
493 | if (settings.engine === undefined) {
494 | settings.engine = "standard";
495 | } else {
496 | settings.engine = settings.engine.toLowerCase();
497 | }
498 | return new self.constructor.prototype.templateEngines[settings.engine](list, settings);
499 | };
500 |
501 | init.start(values, options);
502 | };
503 |
504 | List.prototype.templateEngines = {};
505 | List.prototype.plugins = {};
506 |
507 | List.prototype.templateEngines.standard = function(list, settings) {
508 | var listSource = h.getByClass(settings.listClass, list.listContainer, true),
509 | itemSource = getItemSource(settings.item),
510 | templater = this;
511 |
512 | function getItemSource(item) {
513 | if (item === undefined) {
514 | var nodes = listSource.childNodes,
515 | items = [];
516 |
517 | for (var i = 0, il = nodes.length; i < il; i++) {
518 | // Only textnodes have a data attribute
519 | if (nodes[i].data === undefined) {
520 | return nodes[i];
521 | }
522 | }
523 | return null;
524 | } else if (item.indexOf("<") !== -1) { // Try create html element of list, do not work for tables!!
525 | var div = document.createElement('div');
526 | div.innerHTML = item;
527 | return div.firstChild;
528 | } else {
529 | return document.getElementById(settings.item);
530 | }
531 | }
532 |
533 | var ensure = {
534 | created: function(item) {
535 | if (item.elm === undefined) {
536 | templater.create(item);
537 | }
538 | }
539 | };
540 |
541 | /* Get values from element */
542 | this.get = function(item, valueNames) {
543 | ensure.created(item);
544 | var values = {};
545 | for(var i = 0, il = valueNames.length; i < il; i++) {
546 | var elm = h.getByClass(valueNames[i], item.elm, true);
547 | values[valueNames[i]] = elm ? elm.innerHTML : "";
548 | }
549 | return values;
550 | };
551 |
552 | /* Sets values at element */
553 | this.set = function(item, values) {
554 | ensure.created(item);
555 | for(var v in values) {
556 | if (values.hasOwnProperty(v)) {
557 | // TODO speed up if possible
558 | var elm = h.getByClass(v, item.elm, true);
559 | if (elm) {
560 | elm.innerHTML = values[v];
561 | }
562 | }
563 | }
564 | };
565 |
566 | this.create = function(item) {
567 | if (item.elm !== undefined) {
568 | return;
569 | }
570 | /* If item source does not exists, use the first item in list as
571 | source for new items */
572 | var newItem = itemSource.cloneNode(true);
573 | newItem.id = "";
574 | item.elm = newItem;
575 | templater.set(item, item.values());
576 | };
577 | this.remove = function(item) {
578 | listSource.removeChild(item.elm);
579 | };
580 | this.show = function(item) {
581 | ensure.created(item);
582 | listSource.appendChild(item.elm);
583 | };
584 | this.hide = function(item) {
585 | if (item.elm !== undefined && item.elm.parentNode === listSource) {
586 | listSource.removeChild(item.elm);
587 | }
588 | };
589 | this.clear = function() {
590 | /* .innerHTML = ''; fucks up IE */
591 | if (listSource.hasChildNodes()) {
592 | while (listSource.childNodes.length >= 1)
593 | {
594 | listSource.removeChild(listSource.firstChild);
595 | }
596 | }
597 | };
598 | };
599 |
600 |
601 | /*
602 | * These helper functions are not written by List.js author Jonny (they may have been
603 | * adjusted, thought).
604 | */
605 | h = {
606 | /*
607 | * Cross browser getElementsByClassName, which uses native
608 | * if it exists. Modified version of Dustin Diaz function:
609 | * http://www.dustindiaz.com/getelementsbyclass
610 | */
611 | getByClass: (function() {
612 | if (document.getElementsByClassName) {
613 | return function(searchClass,node,single) {
614 | if (single) {
615 | return node.getElementsByClassName(searchClass)[0];
616 | } else {
617 | return node.getElementsByClassName(searchClass);
618 | }
619 | };
620 | } else {
621 | return function(searchClass,node,single) {
622 | var classElements = [],
623 | tag = '*';
624 | if (node == null) {
625 | node = document;
626 | }
627 | var els = node.getElementsByTagName(tag);
628 | var elsLen = els.length;
629 | var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
630 | for (var i = 0, j = 0; i < elsLen; i++) {
631 | if ( pattern.test(els[i].className) ) {
632 | if (single) {
633 | return els[i];
634 | } else {
635 | classElements[j] = els[i];
636 | j++;
637 | }
638 | }
639 | }
640 | return classElements;
641 | };
642 | }
643 | })(),
644 | /* (elm, 'event' callback) Source: http://net.tutsplus.com/tutorials/javascript-ajax/javascript-from-null-cross-browser-event-binding/ */
645 | addEvent: (function( window, document ) {
646 | if ( document.addEventListener ) {
647 | return function( elem, type, cb ) {
648 | if ((elem && !(elem instanceof Array) && !elem.length && !h.isNodeList(elem) && (elem.length !== 0)) || elem === window ) {
649 | elem.addEventListener(type, cb, false );
650 | } else if ( elem && elem[0] !== undefined ) {
651 | var len = elem.length;
652 | for ( var i = 0; i < len; i++ ) {
653 | h.addEvent(elem[i], type, cb);
654 | }
655 | }
656 | };
657 | }
658 | else if ( document.attachEvent ) {
659 | return function ( elem, type, cb ) {
660 | if ((elem && !(elem instanceof Array) && !elem.length && !h.isNodeList(elem) && (elem.length !== 0)) || elem === window ) {
661 | elem.attachEvent( 'on' + type, function() { return cb.call(elem, window.event); } );
662 | } else if ( elem && elem[0] !== undefined ) {
663 | var len = elem.length;
664 | for ( var i = 0; i < len; i++ ) {
665 | h.addEvent( elem[i], type, cb );
666 | }
667 | }
668 | };
669 | }
670 | })(this, document),
671 | /* (elm, attribute) Source: http://stackoverflow.com/questions/3755227/cross-browser-javascript-getattribute-method */
672 | getAttribute: function(ele, attr) {
673 | var result = (ele.getAttribute && ele.getAttribute(attr)) || null;
674 | if( !result ) {
675 | var attrs = ele.attributes;
676 | var length = attrs.length;
677 | for(var i = 0; i < length; i++) {
678 | if (attr[i] !== undefined) {
679 | if(attr[i].nodeName === attr) {
680 | result = attr[i].nodeValue;
681 | }
682 | }
683 | }
684 | }
685 | return result;
686 | },
687 | /* http://stackoverflow.com/questions/7238177/detect-htmlcollection-nodelist-in-javascript */
688 | isNodeList: function(nodes) {
689 | var result = Object.prototype.toString.call(nodes);
690 | if (typeof nodes === 'object' && /^\[object (HTMLCollection|NodeList|Object)\]$/.test(result) && (nodes.length == 0 || (typeof nodes[0] === "object" && nodes[0].nodeType > 0))) {
691 | return true;
692 | }
693 | return false;
694 | },
695 | hasClass: function(ele, classN) {
696 | var classes = this.getAttribute(ele, 'class') || this.getAttribute(ele, 'className') || "";
697 | return (classes.search(classN) > -1);
698 | },
699 | addClass: function(ele, classN) {
700 | if (!this.hasClass(ele, classN)) {
701 | var classes = this.getAttribute(ele, 'class') || this.getAttribute(ele, 'className') || "";
702 | classes = classes + ' ' + classN + ' ';
703 | classes = classes.replace(/\s{2,}/g, ' ');
704 | ele.setAttribute('class', classes);
705 | }
706 | },
707 | removeClass: function(ele, classN) {
708 | if (this.hasClass(ele, classN)) {
709 | var classes = this.getAttribute(ele, 'class') || this.getAttribute(ele, 'className') || "";
710 | classes = classes.replace(classN, '');
711 | ele.setAttribute('class', classes);
712 | }
713 | },
714 | /*
715 | * The sort function. From http://my.opera.com/GreyWyvern/blog/show.dml/1671288
716 | */
717 | sorter: {
718 | alphanum: function(a,b,asc) {
719 | if (a === undefined || a === null) {
720 | a = "";
721 | }
722 | if (b === undefined || b === null) {
723 | b = "";
724 | }
725 | a = a.toString().replace(/&(lt|gt);/g, function (strMatch, p1){
726 | return (p1 == "lt")? "<" : ">";
727 | });
728 | a = a.replace(/<\/?[^>]+(>|$)/g, "");
729 |
730 | b = b.toString().replace(/&(lt|gt);/g, function (strMatch, p1){
731 | return (p1 == "lt")? "<" : ">";
732 | });
733 | b = b.replace(/<\/?[^>]+(>|$)/g, "");
734 | var aa = this.chunkify(a);
735 | var bb = this.chunkify(b);
736 |
737 | for (var x = 0; aa[x] && bb[x]; x++) {
738 | if (aa[x] !== bb[x]) {
739 | var c = Number(aa[x]), d = Number(bb[x]);
740 | if (asc) {
741 | if (c == aa[x] && d == bb[x]) {
742 | return c - d;
743 | } else {
744 | return (aa[x] > bb[x]) ? 1 : -1;
745 | }
746 | } else {
747 | if (c == aa[x] && d == bb[x]) {
748 | return d-c;//c - d;
749 | } else {
750 | return (aa[x] > bb[x]) ? -1 : 1; //(aa[x] > bb[x]) ? 1 : -1;
751 | }
752 | }
753 | }
754 | }
755 | return aa.length - bb.length;
756 | },
757 | chunkify: function(t) {
758 | var tz = [], x = 0, y = -1, n = 0, i, j;
759 |
760 | while (i = (j = t.charAt(x++)).charCodeAt(0)) {
761 | var m = (i == 45 || i == 46 || (i >=48 && i <= 57));
762 | if (m !== n) {
763 | tz[++y] = "";
764 | n = m;
765 | }
766 | tz[y] += j;
767 | }
768 | return tz;
769 | }
770 | }
771 | };
772 |
773 | window.List = List;
774 | window.ListJsHelpers = h;
775 | })(window);
--------------------------------------------------------------------------------
/output.json:
--------------------------------------------------------------------------------
1 | ---
2 | layout: none
3 | ---
4 | [{% for post in site.posts %}{
5 | "company-name": "{{post.company-name}}",
6 | "city": "{{post.city}}",
7 | "state": "{{post.state}}",
8 | "employees": "{{post.employees}}",
9 | "tags": "{{ post.tags | array_to_sentence_string }}",
10 | "categories": "{{post.categories}}"
11 | }{% if forloop.rindex0 > 0 %},{% endif %}{% endfor %}]
--------------------------------------------------------------------------------
/params.json:
--------------------------------------------------------------------------------
1 | {
2 | "name":"Jekyll-db",
3 | "tagline":"",
4 | "body":"### Welcome to GitHub Pages.\r\nThis automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here using GitHub Flavored Markdown, select a template crafted by a designer, and publish. After your page is generated, you can check out the new branch:\r\n\r\n```\r\n$ cd your_repo_root/repo_name\r\n$ git fetch origin\r\n$ git checkout gh-pages\r\n```\r\n\r\nIf you're using the GitHub for Mac, simply sync your repository and you'll see the new branch.\r\n\r\n### Designer Templates\r\nWe've crafted some handsome templates for you to use. Go ahead and continue to layouts to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved if it remained markdown format.\r\n\r\n### Rather Drive Stick?\r\nIf you prefer to not use the automatic generator, push a branch named `gh-pages` to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator written by our own Tom Preston-Werner. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.\r\n\r\n### Authors and Contributors\r\nYou can @mention a GitHub username to generate a link to their profile. The resulting `` element will link to the contributor's GitHub Profile. For example: In 2007, Chris Wanstrath (@defunkt), PJ Hyett (@pjhyett), and Tom Preston-Werner (@mojombo) founded GitHub.\r\n\r\n### Support or Contact\r\nHaving trouble with Pages? Check out the documentation at http://help.github.com/pages or contact support@github.com and we’ll help you sort it out.\r\n",
5 | "google":"",
6 | "note":"Don't delete this file! It's used internally to help with page regeneration."
7 | }
8 |
--------------------------------------------------------------------------------