1 /* The person who associated a work with this deed has dedicated the
2 work to the public domain by waiving all of his or her rights to
3 the work worldwide under copyright law, including all related and
4 neighboring rights, to the extent allowed by law.
6 You can copy, modify, distribute and perform the work, even for
7 commercial purposes, all without asking permission.
9 See https://creativecommons.org/publicdomain/zero/1.0/ for details.
14 if (!String
.prototype.repeat
)
15 Object
.defineProperty(String
.prototype, "repeat", {
16 value: function (count
) {
17 var string
= this.toString();
31 if (!Array
.prototype.fill
)
32 Object
.defineProperty(Array
.prototype, "fill", {
33 value: function (value
) {
34 var beg
= arguments
.length
> 1 ? +arguments
[1] : 0;
35 var end
= arguments
.length
> 2 ? +arguments
[2] : this.length
;
36 if (beg
< 0) beg
+= this.length
;
37 if (end
< 0) end
+= this.length
;
38 for (var i
= beg
; i
< end
; ++i
)
44 if (!Element
.prototype.matches
)
45 Object
.defineProperty(Element
.prototype, "matches", {
46 value
: Element
.prototype.matchesSelector
47 || Element
.prototype.mozMatchesSelector
48 || Element
.prototype.webkitMatchesSelector
51 function removeUnit (element
) {
52 element
.parentNode
.removeChild(element
);
57 var FIRST_EMPTY
= /☐/;
58 var LAST_TICKED
= /☒([^☒]*)$/;
60 function randomName (scheme
) {
61 return G
.expand(scheme
);
64 var STATS
= ["attack", "range", "defense", "aside"];
65 function createUnit (dfnName
) {
66 var dfn
= UNITS
[dfnName
];
67 var weapons
= dfn
.weapons
|| [];
68 var unit
= document
.getElementById("unit-template").cloneNode(true);
69 unit
.removeAttribute('id');
70 unit
.setAttribute("data-dfn", dfnName
);
71 unit
.querySelector(".name").textContent
= randomName(dfn
.nameScheme
);
72 unit
.querySelector(".type").textContent
= dfnName
;
75 var aside
= unit
.appendChild(document
.createElement("div"));
76 aside
.className
= "aside";
77 aside
.innerHTML
= dfn
.aside
;
80 var weaponList
= unit
.appendChild(document
.createElement('ul'));
81 weaponList
.className
= "weapons";
84 weapons
.forEach(function (weaponRef
) {
85 var count
= parseInt(weaponRef
, 10) || 1;
86 var weaponName
= weaponRef
.replace(/^[0-9 ]*/, "");
87 var weapon
= WEAPONS
[weaponName
]
88 || WEAPONS
[weaponName
.replace(/s+$/, "")];
89 var weaponItem
= document
.createElement("li");
90 weaponItem
.setAttribute('data-name', weaponName
);
91 weaponItem
.setAttribute('data-count', count
);
92 weaponItem
.setAttribute('data-remaining', count
);
93 var stats
= document
.createElement('ul');
94 stats
.className
= "stats";
95 for (var j
= 0; j
< STATS
.length
; ++j
) {
96 if (weapon
[STATS
[j
]] !== undefined) {
97 var stat
= document
.createElement('li');
98 stat
.className
= STATS
[j
];
99 stat
.innerHTML
= weapon
[STATS
[j
]];
100 stats
.appendChild(stat
);
103 if (stats
.children
.length
)
104 weaponItem
.appendChild(stats
);
105 var ticks
= document
.createElement('div');
106 ticks
.className
= "ticks";
107 ticks
.innerHTML
= ticksText(count
);
108 weaponItem
.appendChild(ticks
);
109 weaponList
.appendChild(weaponItem
);
113 var move = dfn
.move || 3;
114 var per
= dfn
.tread
/ move;
115 var treads
= document
.createElement('ol');
116 treads
.className
= "treads";
117 treads
.appendChild(document
.createElement("li"));
118 treads
.setAttribute('data-count', dfn
.tread
);
119 treads
.setAttribute('data-remaining', dfn
.tread
);
120 for (var i
= 0; i
< move; ++i
) {
121 var tread
= treads
.appendChild(document
.createElement("li"));
122 tread
.className
= "ticks";
123 tread
.innerHTML
= ticksText(per
);
125 unit
.appendChild(treads
);
127 if (dfn
.propulsion
) {
128 var move = dfn
.move || 3;
129 var per
= dfn
.propulsion
/ move;
130 var treads
= document
.createElement('ol');
131 treads
.className
= "treads propulsion";
132 treads
.appendChild(document
.createElement("li"));
133 treads
.setAttribute('data-count', dfn
.propulsion
);
134 treads
.setAttribute('data-remaining', dfn
.propulsion
);
135 for (var i
= 0; i
< move; ++i
) {
136 var tread
= treads
.appendChild(document
.createElement("li"));
137 tread
.className
= "ticks";
138 tread
.innerHTML
= ticksText(per
);
140 unit
.appendChild(treads
);
146 function addUnit (dfnName
) {
147 document
.querySelector('main').appendChild(createUnit(dfnName
));
151 return new RegExp("(^|\\s+)" + c
+ "(\\s+|$)");
154 function hasClass (e
, n
) {
155 return !!e
.className
.match(spre(n
));
158 function addClass (e
, n
) {
160 e
.className
+= " " + n
;
163 function removeClass (e
, n
) {
164 e
.className
= e
.className
.replace(spre(n
), "");
168 addClass(document
.getElementById(id
.id
|| id
), "visible");
171 removeClass(document
.getElementById(id
.id
|| id
), "visible");
173 function handleTray (evt
) {
174 var id
= this.getAttribute('data-tray');
175 var el
= document
.getElementById(id
);
176 var f
= (hasClass(el
, "visible") ? hide
: show
)
179 evt
.stopPropagation();
182 function ticksText (n
) {
183 var blocks
= [EMPTY
.repeat(n
)];
184 for (var i
= 5; i
>= 2; --i
) {
185 if (n
> i
&& n
% i
=== 0) {
186 blocks
= (new Array(n
/ i
)).fill(EMPTY
.repeat(i
));
190 return "<span>" + blocks
.join("</span><wbr><span>") + "</span>";
193 function rub (content
) {
194 return content
.replace(LAST_TICKED
, EMPTY
+ "$1");
196 function tick (content
) {
197 return content
.replace(FIRST_EMPTY
, CHECK
);
200 function findParent (el
, selector
) {
201 while (el
&& el
!== document
&& !el
.matches(selector
))
203 return el
=== document
? null : el
;
206 function boxes (event
) {
207 var target
= event
.target
;
208 if (!target
.innerHTML
.match(/☐|☒/))
210 var par
= findParent(target
, '[data-count]');
211 var ticks
= findParent(target
, '.ticks');
214 var content
= target
.innerHTML
;
215 var rect
= target
.getBoundingClientRect();
216 var total
= target
.innerHTML
.match(/☐|☒/g);
217 var ticked
= target
.innerHTML
.match(/☒/g);
218 var p
= (event
.clientX
- rect
.left
) / rect
.width
;
219 var pr
= (total
&& total
.length
)
220 ? (ticked
? ticked
.length
: 0) / total
.length
: 0;
221 par
.innerHTML
= ((p
< pr
) ? rub
: tick
)(par
.innerHTML
);
222 var rem
= par
.innerHTML
.match(/☐/g);
223 par
.setAttribute('data-remaining', rem
? rem
.length
: 0);
224 event
.preventDefault();
225 event
.stopPropagation();
229 return p
* p
* p
* (p
* (p
* 6.0 - 15.0) + 10.0);
232 function scroll (y1
, t
) {
233 var y0
= document
.body
.scrollTop
|| document
.documentElement
.scrollTop
;
234 var n
= (t
|| 150) / 15;
236 clearInterval(scroll
.owner
);
237 scroll
.owner
= setInterval(function () {
238 var p
= Math
.max(0, Math
.min(++i
/ n
, 1));
239 document
.body
.scrollTop
240 = document
.documentElement
.scrollTop
241 = y0
+ (y1
- y0
) * fade(p
);
242 if (i
>= n
) clearInterval(scroll
.owner
);
247 scroll(el
.nextElementSibling
.offsetTop
- el
.parentNode
.offsetTop
);
250 function previous (el
) {
251 scroll(el
.previousElementSibling
.offsetTop
- el
.parentNode
.offsetTop
);
254 function autoClose () {
255 var open
= document
.querySelectorAll(".tray.visible");
256 for (var i
= 0; i
< open
.length
; ++i
)
258 return open
&& open
.length
;
261 window
.addEventListener("DOMContentLoaded", function () {
262 if (navigator
.standalone
)
263 document
.body
.className
+= " standalone";
264 var units
= document
.getElementById("addUnit");
265 Object
.keys(UNITS
).sort(function (a
, b
) {
266 return (b
.indexOf("Ogre Mk") - a
.indexOf("Ogre Mk"))
267 || (a
> b
) - (a
< b
);
268 }).forEach(function (unitName
) {
269 var unit
= units
.appendChild(document
.createElement("li"));
270 unit
.textContent
= unitName
;
271 unit
.addEventListener("click", function () {
276 addUnit('Ogre Mk. V');
277 FastClick
.attach(document
.body
, { tapDelay
: 50 });
279 var trays
= document
.querySelectorAll('[data-tray]');
280 for (var i
= 0; i
< trays
.length
; ++i
)
281 trays
[i
].addEventListener('click', handleTray
);
282 window
.addEventListener('click', function (evt
) {
283 if (!findParent(evt
.target
, ".tray.visible"))