Added basic printing functionality

This commit is contained in:
Stefan Zermatten
2017-07-03 12:25:07 +02:00
parent 0b8fabde14
commit 00a050d337
16 changed files with 505 additions and 0 deletions

View File

@@ -0,0 +1,174 @@
// jscs:disable
// https://github.com/chunksnbits/jquery-quickfit
(function ($) {
var Quickfit, QuickfitHelper, defaults, pluginName;
pluginName = 'quickfit';
defaults = {
min: 8,
max: 12,
tolerance: 0.02,
truncate: false,
width: null,
sampleNumberOfLetters: 10,
sampleFontSize: 12
};
QuickfitHelper = (function () {
var sharedInstance = null;
QuickfitHelper.instance = function (options) {
if (!sharedInstance) {
sharedInstance = new QuickfitHelper(options);
}
return sharedInstance;
};
function QuickfitHelper(options) {
this.options = options;
this.item = $('<span id="meassure"></span>');
this.item.css({
position: 'absolute',
left: '-1000px',
top: '-1000px',
'font-size': "" + this.options.sampleFontSize + "px"
});
$('body').append(this.item);
this.meassures = {};
}
QuickfitHelper.prototype.getMeassure = function (letter) {
var currentMeassure;
currentMeassure = this.meassures[letter];
if (!currentMeassure) {
currentMeassure = this.setMeassure(letter);
}
return currentMeassure;
};
QuickfitHelper.prototype.setMeassure = function (letter) {
var currentMeassure, index, sampleLetter, text, _ref;
text = '';
sampleLetter = letter === ' ' ? '&nbsp;' : letter;
for (index = 0, _ref = this.options.sampleNumberOfLetters - 1; 0 <= _ref ? index <= _ref : index >= _ref; 0 <= _ref ? index++ : index--) {
text += sampleLetter;
}
this.item.html(text);
currentMeassure = this.item.width() / this.options.sampleNumberOfLetters / this.options.sampleFontSize;
this.meassures[letter] = currentMeassure;
return currentMeassure;
};
return QuickfitHelper;
})();
Quickfit = (function () {
function Quickfit(element, options) {
this.$element = element;
this.options = $.extend({}, defaults, options);
this.$element = $(this.$element);
this._defaults = defaults;
this._name = pluginName;
this.quickfitHelper = QuickfitHelper.instance(this.options);
}
Quickfit.prototype.fit = function () {
var elementWidth;
if (!this.options.width) {
elementWidth = this.$element.width();
this.options.width = elementWidth - this.options.tolerance * elementWidth;
}
if (this.text = this.$element.attr('data-quickfit')) {
this.previouslyTruncated = true;
} else {
this.text = this.$element.text();
}
this.calculateFontSize();
if (this.options.truncate) this.truncate();
return {
$element: this.$element,
size: this.fontSize
};
};
Quickfit.prototype.calculateFontSize = function () {
var letter, textWidth, i;
textWidth = 0;
for (i = 0; i < this.text.length; ++i) {
letter = this.text.charAt(i);
textWidth += this.quickfitHelper.getMeassure(letter);
}
this.targetFontSize = parseInt(this.options.width / textWidth);
return this.fontSize = Math.max(this.options.min, Math.min(this.options.max, this.targetFontSize));
};
Quickfit.prototype.truncate = function () {
var index, lastLetter, letter, textToAdd, textWidth;
if (this.fontSize > this.targetFontSize) {
textToAdd = '';
textWidth = 3 * this.quickfitHelper.getMeassure('.') * this.fontSize;
index = 0;
while (textWidth < this.options.width && index < this.text.length) {
letter = this.text[index++];
if (lastLetter) textToAdd += lastLetter;
textWidth += this.fontSize * this.quickfitHelper.getMeassure(letter);
lastLetter = letter;
}
if (textToAdd.length + 1 === this.text.length) {
textToAdd = this.text;
} else {
textToAdd += '...';
}
this.textWasTruncated = true;
return this.$element.attr('data-quickfit', this.text).html(textToAdd);
} else {
if (this.previouslyTruncated) {
return this.$element.html(this.text);
}
}
};
return Quickfit;
})();
return $.fn.quickfit = function (options) {
var measurements = [];
// Separate measurements from repaints
// First calculate all measurements...
var $elements = this.each(function () {
var measurement = new Quickfit(this, options).fit();
measurements.push(measurement);
return measurement.$element;
});
// ... then apply the measurements.
for (var i = 0; i < measurements.length; i++) {
var measurement = measurements[i];
measurement.$element.css({ fontSize: measurement.size + 'px' });
}
return $elements;
};
})(jQuery, window);

View File

@@ -0,0 +1,12 @@
Session.setDefault("isPrinting", false);
if (window.matchMedia) {
var mediaQueryList = window.matchMedia("print");
mediaQueryList.addListener(function(mql) {
if (mql.matches) {
Session.set("isPrinting", true);
Tracker.flush();
} else {
Session.set("isPrinting", false);
}
});
}

View File

@@ -1,4 +1,7 @@
<template name="characterSheet">
{{#if printing}}
{{> printedCharacterSheet}}
{{/if}}
<div class="fit layout vertical character-sheet">
<app-header fixed effects="waterfall">
<app-toolbar class="medium-tall {{colorClass}}">

View File

@@ -165,6 +165,9 @@ var getTab = function(charId){
};
Template.characterSheet.helpers({
printing: function(){
return Session.get("isPrinting");
},
selectedTab: function(){
return getTab(this._id);
},

View File

@@ -0,0 +1,13 @@
<template name="printedAbility">
<div class="printedAbility layout vertical center">
<div class="paper-font-subhead title flex layout horizontal center">
{{title}}
</div>
<div class="paper-font-display1 stat">
{{characterCalculate "attributeValue" ../_id ability}}
</div>
<div class="paper-font-subhead modifier">
{{abilityMod}}
</div>
</div>
</template>

View File

@@ -0,0 +1,9 @@
Template.printedAbility.helpers({
abilityMod: function() {
return signedString(
Characters.calculate.abilityMod(
Template.parentData()._id, this.ability
)
);
}
});

View File

@@ -0,0 +1,37 @@
.printed {
background: #fff;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 99;
}
.printed > .page {
width: 100%;
padding: 1cm;
page-break-inside: avoid;
page-break-after: always;
}
.printed .shrink-to-fit {
white-space: nowrap;
overflow: hidden;
}
@media screen {
.printed {
display: none;
}
}
@media print {
.character-sheet {
display: none;
}
app-drawer {
display: none;
}
}

View File

@@ -0,0 +1,116 @@
<template name="printedCharacterSheet">
<div class="printed">
<div class="page">
<div class="layout vertical">
<div class="layout horizontal">
<div class="characterName paper-font-title">
{{name}}
</div>
<div>
<div>
{{#each classes}}
<span style="margin-right: 16px;">
{{name}}&nbsp;{{level}}
</span>
{{/each}}
</div>
<div>
{{alignment}} {{gender}} {{race}}
</div>
</div>
</div>
<div class="layout horizontal">
<div class="col1 padded flex layout vertical">
<div class="layout horizontal">
<div class="abilities padded layout vertical justified">
{{> printedAbility ability="strength" title="Strength" color="red"}}
{{> printedAbility ability="dexterity" title="Dexterity" color="indigo"}}
{{> printedAbility ability="constitution" title="Constitution" color="green"}}
{{> printedAbility ability="intelligence" title="Intelligence" color="deep-orange"}}
{{> printedAbility ability="wisdom" title="Wisdom" color="purple"}}
{{> printedAbility ability="charisma" title="Charisma" color="pink"}}
</div>
<div class="padded flex layout vertical">
<div class="proficiencyBonus">
{{> printedLongStat stat="proficiencyBonus" name="Proficiency Bonus" prefix="+"}}
</div>
<div class="saves">
<div class="paper-font-subhead">
Saving Throws
</div>
<div>
{{> printedSkillRow name="Strength" skill="strengthSave"}}
{{> printedSkillRow name="Dexterity" skill="dexteritySave"}}
{{> printedSkillRow name="Constitution" skill="constitutionSave"}}
{{> printedSkillRow name="Intelligence" skill="intelligenceSave"}}
{{> printedSkillRow name="Wisdom" skill="wisdomSave"}}
{{> printedSkillRow name="Charisma" skill="charismaSave"}}
</div>
</div>
<div class="skills">
<div class="paper-font-subhead">
Skills
</div>
<div>
{{> printedSkillRow name="Acrobatics" skill="acrobatics"}}
{{> printedSkillRow name="Animal Handling" skill="animalHandling"}}
{{> printedSkillRow name="Arcana" skill="arcana"}}
{{> printedSkillRow name="Athletics" skill="athletics"}}
{{> printedSkillRow name="Deception" skill="deception"}}
{{> printedSkillRow name="History" skill="history"}}
{{> printedSkillRow name="Insight" skill="insight"}}
{{> printedSkillRow name="Intimidation" skill="intimidation"}}
{{> printedSkillRow name="Investigation" skill="investigation"}}
{{> printedSkillRow name="Medicine" skill="medicine"}}
{{> printedSkillRow name="Nature" skill="nature"}}
{{> printedSkillRow name="Perception" skill="perception" showPassive="true"}}
{{> printedSkillRow name="Performance" skill="performance"}}
{{> printedSkillRow name="Persuasion" skill="persuasion"}}
{{> printedSkillRow name="Religion" skill="religion"}}
{{> printedSkillRow name="Sleight of Hand" skill="sleightOfHand"}}
{{> printedSkillRow name="Stealth" skill="stealth"}}
{{> printedSkillRow name="Survival" skill="survival"}}
</div>
</div>
</div>
</div>
<div class="proficiencies">
</div>
</div>
<div class="col2 padded flex">
<div class="layout vertical">
<div class="layout horizontal justified">
<div class="armor">
{{> printedSquareStat stat="armor" name="Armor Class" color="teal"}}
</div>
<div class="inititive">
{{> printedSquareStat stat="initiative" name="Initiative" color="teal"}}
</div>
<div class="speed">
{{> printedSquareStat stat="speed" name="Speed" color="teal"}}
</div>
</div>
<div class="hitpoints padded layout vertical">
<div>Hit Points</div>
<div style="width: 3cm; height: 2cm;">
<!-- Space for writing-->
</div>
<div class="layout horizontal end-justified">
/{{characterCalculate "attributeValue" _id "hitPoints"}}
</div>
</div>
<div class="tempHitpoints"></div>
<div class="layout horizontal">
<div class="hitDice"></div>
<div class="deathSaves"></div>
</div>
</div>
<div class="attacks"></div>
<div class="persona"></div>
</div>
</div>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,17 @@
Template.printedCharacterSheet.onRendered(function(){
// Quickfit is only called once on rendering, text will not resize reactively
this.$(".shrink-to-fit").quickfit({
min: 7,
max: 36,
truncate: true,
});
});
Template.printedCharacterSheet.helpers({
character(){
return Characters.findOne(this._id);
},
classes: function(){
return Classes.find({charId: this._id}, {sort: {createdAt: 1}});
},
});

View File

@@ -0,0 +1,14 @@
<template name="printedLongStat">
<div class="printedLongStat layout horizontal">
<div class="numbers paper-font-display1">
{{#if isSkill}}
{{prefix}}{{skillMod}}
{{else}}
{{prefix}}{{characterCalculate "attributeValue" ../_id stat}}
{{/if}}
</div>
<div class="paper-font-subhead title flex layout horizontal center">
{{name}}
</div>
</div>
</template>

View File

@@ -0,0 +1,9 @@
Template.printedLongStat.helpers({
skillMod: function() {
return signedString(
Characters.calculate.skillMod(
Template.parentData()._id, this.stat
)
);
},
});

View File

@@ -0,0 +1,21 @@
<template name="printedSkillRow">
<div class="printedSkillRow layout horizontal center">
<iron-icon icon="{{profIcon}}"></iron-icon>
{{#if failSkill}}
<div class="fail skill-mod">fail</div>
{{else}}
<div class="{{advantage}} skill-mod">
{{skillMod}}
</div>
{{/if}}
<div flex>
{{name}}
{{#if conditionalCount}}
*
{{/if}}
{{#if showPassive}}
({{characterCalculate "passiveSkill" ../_id skill}})
{{/if}}
</div>
</div>
</template>

View File

@@ -0,0 +1,41 @@
Template.printedSkillRow.helpers({
skillMod: function() {
return signedString(
Characters.calculate.skillMod(
Template.parentData()._id, this.skill
)
);
},
profIcon: function(){
var charId = Template.parentData()._id;
var prof = Characters.calculate.proficiency(charId, this.skill);
if (prof > 0 && prof < 1) return "image:brightness-2";
if (prof === 1) return "image:brightness-1";
if (prof > 1) return "av:album";
return "radio-button-unchecked";
},
failSkill: function(){
var charId = Template.parentData()._id;
return Effects.find({
charId: charId,
stat: this.skill,
enabled: true,
operation: "fail",
}).count();
},
advantage: function(){
var charId = Template.parentData()._id;
var advantage = Characters.calculate.advantage(charId, this.skill);
if (advantage > 0) return "advantage";
if (advantage < 0) return "disadvantage";
},
conditionalCount: function(){
var charId = Template.parentData()._id;
return Effects.find({
charId: charId,
stat: this.skill,
enabled: true,
operation: "conditional",
}).count();
},
});

View File

@@ -0,0 +1,14 @@
<template name="printedSquareStat">
<div class="printedSquareStat padded layout vertical center">
<div class="paper-font-subhead">
{{name}}
</div>
<div class="numbers paper-font-display1">
{{#if isSkill}}
{{prefix}}{{skillMod}}
{{else}}
{{prefix}}{{characterCalculate "attributeValue" ../_id stat}}
{{/if}}
</div>
</div>
</template>

View File

@@ -0,0 +1,9 @@
Template.printedSquareStat.helpers({
skillMod: function() {
return signedString(
Characters.calculate.skillMod(
Template.parentData()._id, this.stat
)
);
},
});

View File

@@ -23,4 +23,17 @@
<meta name="msapplication-TileColor" content="#b91d1d">
<meta name="msapplication-TileImage" content="/mstile-144x144.png?v=lk6WXp6Pmj">
<meta name="theme-color" content="#d12929">
<style type="text/css" media="print">
@page {
margin: 0mm;
}
html {
margin: 0px;
}
* {
-webkit-transition: none !important;
transition: none !important;
}
</style>
</head>