├── .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 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% for post in site.posts %} 19 | 20 | 21 | 22 | 23 | 24 | 25 | {% endfor %} 26 | 27 |
Company NameCityCategoryTags
{{ post.company-name }}{{ post.city }}{{ post.categories }}{{ post.tags | array_to_sentence_string }}
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 | Fork me on GitHub 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 |
18 |

Built with Jekyll + ListJS + Bootstrap. See the readme for instruction on how to use..

19 |
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 | --------------------------------------------------------------------------------