Knockback Rendered WOD Sheet

A NR WOD sheet rendered entirely with Knockback.js and CSS.

by Troy Alford

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div data-bind="foreach: $.map(Sheet.groups, function(group, ix) { return { label: ix, value: group }; })">
  <div class="section" data-bind="attr: { name: label }">
    <h5 data-bind="text: label"></h5>
    <!-- ko foreach: value -->
    <div class="text stat">
      <div class="dots value" data-bind="if: ($data.score != undefined)">
        <!-- ko foreach: _.seq($root.Settings.global.maxScore() || 5) -->
        <div data-bind="attr: { class: 'dot' + (($data <= $parent.score()) ? ' filled' : '') }"></div>
        <!-- /ko -->
      </div>
      <div class="text label" data-bind="text: $data.label"></div>
      <!-- ko if: $data.text -->
        <div class="text value" data-bind="text: $data.text"></div>
      <!-- /ko -->
    </div>
    <!-- /ko -->
  </div>
</div>

SCSS

* { 
  font-size: 10px; 
  font-family: Calibri;
  box-sizing: border-box;
}

.stat { padding: 0 5px; width: 250px; }

.section { 
  display: block;
  float: left;
  width: 250px;
  
  > h5 { 
    font-size: 1.8rem; 
    font-weight: bold;
    text-align: center;
  }
}

.text {
  display: inline-block;
  font-size: 1.2rem;
  line-height: 20px;

  &.value { float: right; width: 140px; }
  &.label { float: left; font-weight: bold; width: 100px; }
}
/*
.dots.value + .text.label + .text.value {
  display: block;
  padding-left: 15px;
  position: relative;
  width: 100%;
  
  &:before {
    content: '';
    display: inline-block;
    position: absolute;
    left: 3px; top: 3px;
    width: 9px; height: 9px;
    border: 1px dotted #666;
    border-width: 0 0 1px 1px;
  }
}
*/

.dots {
  float: right;
  display: inline-block;
  
  .dot {
    border: 1px solid #000;
    border-radius: 4px;
    display: inline-block;
    height: 8px; width: 8px;
    padding: 3px 1px;
    
    &.filled { background: #000; }
  }
}

[name="general"] {
  width: 760px;
}

JavaScript

var raw = '{"groups":{"general":[{"label":"Title","text":"The Blood Lord"},{"label":"Sobriquette","text":"Baalfron"},{"label":"Concept","text":"Fallen Priest"},{"label":"Virtue","text":"Charity"},{"label":"Vice","text":"Envy"},{"label":"Chronicle","text":"TCS12"},{"label":"Faction","text":"His Own"},{"label":"Group Name"}],"mental-attributes":[{"label":"Intelligence","score":7},{"label":"Wits","score":5},{"label":"Resolve","score":8}],"physical-attributes":[{"label":"Strength","score":2},{"label":"Dexterity","score":2},{"label":"Stamina","score":4}],"social-attributes":[{"label":"Presence","score":2},{"label":"Manipulation","score":2},{"label":"Composure","score":6}],"mental-skills":[{"label":"Academics","score":7},{"label":"Crafts","score":0},{"label":"Hearth Wisdom","score":4},{"label":"Investigation","score":6},{"label":"Medicine","score":5},{"label":"Occult","score":9},{"label":"Politics","score":0},{"label":"Theology","score":7}],"physical-skills":[{"label":"Archery","score":0},{"label":"Athletics","score":0},{"label":"Brawl","score":0},{"label":"Larceny","score":0},{"label":"Ride","score":3},{"label":"Stealth","score":1},{"label":"Survival","score":3},{"label":"Weaponry","score":0}],"social-skills":[{"label":"Animal Ken","score":2},{"label":"Empathy","score":4},{"label":"Expression","score":3},{"label":"Intimidation","score":2},{"label":"Persuasion","score":0},{"label":"Socialize","score":1},{"label":"Streetwise","score":0},{"label":"Subterfuge","score":0}],"merits":[{"label":"Clr: Evocation","score":4},{"label":"Clr: Necromancy","score":9},{"label":"Sor: Illusion","score":3},{},{},{},{},{"label":"Unholy Fortitude","text":"Immune to Bashing;;+4 Damage Reduction vs Lethal;;+4 Soak vs Aggravated","score":4},{"label":"Unholy Potence","text":"+4 Successes on Str Checks"}],"flaws":[{},{},{}],"combat":[{"label":"Size","text":"5"},{"label":"Speed","text":"13"},{"label":"Initiative...