Skip to content
This repository was archived by the owner on May 13, 2024. It is now read-only.

Commit bd2a588

Browse files
committed
Improves load time, and cleans up padding and footer styles
1 parent 7773f63 commit bd2a588

9 files changed

Lines changed: 217 additions & 65 deletions

File tree

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ <h2><em>13th Age</em> fair encounter generator</h2>
5353
</div>
5454

5555
<footer>
56-
<div>
56+
<div class="clearfix">
5757
<section class="fire-opal">
5858
<p>
5959
This program uses trademarks and/or copyrights owned by Fire Opal

src/ts/appcache.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ module manticore.appcache {
3535

3636
inPageConfirm(interface.strings._("There is a new version of this app available. "),
3737
interface.strings._("Reload?"))
38-
.map<any>(_ => location.reload());
38+
.then<any>(_ => location.reload());
3939
}
4040

4141
export function handleReloads () {

src/ts/bestiary.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module manticore.bestiary {
1313
level:number,
1414
size:string,
1515
kind:string,
16-
attributes: Array<string>,
16+
attributes: string[],
1717
book: string,
1818
public price:number) {
1919
super(name, level, size, kind, attributes, book);
@@ -175,7 +175,7 @@ module manticore.bestiary {
175175

176176

177177
// allocateMonster is the core algorithm of this application.
178-
function repeatMonster(points, monster):Array<MonsterAllocation> {
178+
function repeatMonster(points, monster):MonsterAllocation[] {
179179
var max = Math.floor(points / monster.price);
180180
var repeats = [];
181181
for (var i = 1; i <= max; i++) {
@@ -185,15 +185,15 @@ module manticore.bestiary {
185185
}
186186

187187

188-
function allocateMonsters(points:number, monsters:Array<PricedMonster>) {
188+
function allocateMonsters(points:number, monsters:PricedMonster[]) {
189189
var allAllocations = [];
190190
var allowedUnspent = Math.min.apply(null, monsters.map((m) => m.price));
191191

192192
var startT = +new Date();
193193

194194
function allocate(remainingPoints:number,
195195
monstersIdx:number,
196-
acc:Array<MonsterAllocation>) {
196+
acc:MonsterAllocation[]) {
197197

198198
// cap runtime to 2 seconds
199199
if (+new Date() - startT >= 2000) throw { message: "Ran too long; Results truncated" };
@@ -241,7 +241,7 @@ module manticore.bestiary {
241241

242242
// public API:
243243
export function allocationsForParty(party:data.IParty,
244-
selectedMonsters:Array<data.Monster>) {
244+
selectedMonsters:data.Monster[]) {
245245

246246
return allocateMonsters(priceParty(party.size),
247247
selectedMonsters

src/ts/data.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,4 @@ module manticore.data {
118118

119119
return allPredicate(predicates);
120120
}
121-
122-
123-
124-
125121
}

src/ts/interface.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
module manticore.interface {
66
var _ = strings._;
77

8-
function arrayFrom<T>(arrayLike):T[] {
9-
return Array.prototype.slice.apply(arrayLike);
10-
}
11-
128
function cssClassName(text:string):string {
139
return text.replace(/[^-a-zA-Z0-9]+/g, "-");
1410
}
@@ -160,7 +156,7 @@ module manticore.interface {
160156
}
161157

162158
public getSelectedAttributes() {
163-
var selected = arrayFrom<HTMLElement>(this.el.querySelectorAll("li"))
159+
var selected = Array.from<Node>(this.el.querySelectorAll("li"))
164160
.map<string>((el:HTMLElement) =>
165161
el.classList.contains("selected") ? el.getAttribute("data-name") : null)
166162
.filter((attr) => !!attr)
@@ -170,8 +166,8 @@ module manticore.interface {
170166
}
171167

172168
public updateFilterCounts(filters:{[index: string]: number}) {
173-
arrayFrom<HTMLElement>(this.el.querySelectorAll("li"))
174-
.forEach((el) => {
169+
Array.from<Node>(this.el.querySelectorAll("li"))
170+
.forEach((el:HTMLElement) => {
175171
var name = el.getAttribute("data-name");
176172
var count = filters[name] || 0;
177173

@@ -533,7 +529,7 @@ module manticore.interface {
533529
//bestiary = bestiary.then(awaitDelay(2000));
534530

535531
bestiary
536-
.map<void>((bestiary) => {
532+
.then<void>((bestiary) => {
537533
new UI(allocator, bestiary, root);
538534
})
539535
.catch((e) => {

src/ts/manticore.ts

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,44 @@ module manticore {
2626
return acc;
2727
}
2828
}
29+
2930

30-
document.addEventListener("DOMContentLoaded", (e) => {
31-
var root = document.getElementById("application");
31+
function awaitContentLoaded() {
32+
return new Promise((resolve, reject) => {
33+
document.addEventListener("DOMContentLoaded", _ => {
34+
manticore.appcache.handleReloads();
35+
resolve(null);
36+
})
37+
});
38+
}
3239

33-
var dataset = Promise.all<string>([
34-
awaitAjax("static/data/bestiary.json"),
35-
awaitAjax("static/data/custom.json")
36-
.then<string>(resp => Promise.of<string>(resp),
37-
_ => Promise.of<string>("{}")
38-
)
39-
])
40-
// this looks wacky, but is due to the additional arguments of map conflicting
41-
// with the optional arguments parse
42-
.map<any[]>((texts:string[]) => texts.map((s) => JSON.parse(s)))
43-
.map<any>(mergeWith<any[]>((a, b) => a.concat(b)))
44-
.map<bestiary.Bestiary>(bestiary.createBestiary)
45-
;
4640

47-
manticore.appcache.handleReloads();
41+
// Bootstrap application
42+
//
43+
// Immediately request the data. The interface waits on this and
44+
// (in parallel) DOMContentLoaded before it appears.
45+
// Not awaiting DOMContentLoaded to begin loading data ensures a faster
46+
// turn around.
47+
48+
var dataset = Promise.all<string>([
49+
awaitAjax("static/data/bestiary.json"),
50+
awaitAjax("static/data/custom.json")
51+
.then<string>(resp => Promise.resolve<string>(resp),
52+
_ => Promise.resolve<string>("{}")
53+
)
54+
])
55+
// this looks wacky, but is due to the additional arguments of then conflicting
56+
// with the optional arguments parse
57+
.then<any[]>((texts:string[]) => texts.map((s) => JSON.parse(s)))
58+
.then<any>(mergeWith<any[]>((a, b) => a.concat(b)))
59+
.then<bestiary.Bestiary>(bestiary.createBestiary)
60+
;
4861

49-
interface.initialize(
50-
root,
51-
dataset,
52-
bestiary.allocationsForParty
53-
);
54-
});
62+
interface.initialize(
63+
document.getElementById("application"),
64+
Promise.all([dataset, awaitContentLoaded()])
65+
.then(all => all[0])
66+
.catch(e => console.error("An error occured bootstrapping the application", e)),
67+
bestiary.allocationsForParty
68+
);
5569
}

src/ts/shims.ts

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,6 @@ function awaitAjax(url:string, method?:string):Promise<string> {
4848
}
4949

5050

51-
// implement functors on promises so that .then isnt so gross.
52-
//
53-
// exchanging one evil (duckwrapping) for another (monkeypatching a core type)
54-
if (typeof Promise.of == "undefined") {
55-
Promise.of = function (v) {
56-
return new Promise((resolve, _) => resolve(v));
57-
};
58-
}
59-
60-
if (typeof Promise.prototype.map == "undefined") {
61-
Promise.prototype.map = function (fn) {
62-
return this.then((data) => Promise.of(fn(data)));
63-
};
64-
}
65-
66-
6751

6852
// array polyfils taken from developer.mozilla.org
6953

@@ -240,3 +224,89 @@ if (!Array.prototype.forEach) {
240224
};
241225
}
242226

227+
228+
if (!Array.of) {
229+
Array.of = function() {
230+
return Array.prototype.slice.call(arguments);
231+
};
232+
}
233+
234+
235+
// Production steps of ECMA-262, Edition 6, 22.1.2.1
236+
// Reference: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from
237+
if (!Array.from) {
238+
Array.from = (function () {
239+
var toStr = Object.prototype.toString;
240+
var isCallable = function (fn) {
241+
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
242+
};
243+
var toInteger = function (value) {
244+
var number = Number(value);
245+
if (isNaN(number)) { return 0; }
246+
if (number === 0 || !isFinite(number)) { return number; }
247+
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
248+
};
249+
var maxSafeInteger = Math.pow(2, 53) - 1;
250+
var toLength = function (value) {
251+
var len = toInteger(value);
252+
return Math.min(Math.max(len, 0), maxSafeInteger);
253+
};
254+
255+
// The length property of the from method is 1.
256+
return function from(arrayLike/*, mapFn, thisArg */) {
257+
// 1. Let C be the this value.
258+
var C = this;
259+
260+
// 2. Let items be ToObject(arrayLike).
261+
var items = Object(arrayLike);
262+
263+
// 3. ReturnIfAbrupt(items).
264+
if (arrayLike == null) {
265+
throw new TypeError("Array.from requires an array-like object - not null or undefined");
266+
}
267+
268+
// 4. If mapfn is undefined, then let mapping be false.
269+
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
270+
var T;
271+
if (typeof mapFn !== 'undefined') {
272+
// 5. else
273+
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
274+
if (!isCallable(mapFn)) {
275+
throw new TypeError('Array.from: when provided, the second argument must be a function');
276+
}
277+
278+
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
279+
if (arguments.length > 2) {
280+
T = arguments[2];
281+
}
282+
}
283+
284+
// 10. Let lenValue be Get(items, "length").
285+
// 11. Let len be ToLength(lenValue).
286+
var len = toLength(items.length);
287+
288+
// 13. If IsConstructor(C) is true, then
289+
// 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len.
290+
// 14. a. Else, Let A be ArrayCreate(len).
291+
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
292+
293+
// 16. Let k be 0.
294+
var k = 0;
295+
// 17. Repeat, while k < len… (also steps a - h)
296+
var kValue;
297+
while (k < len) {
298+
kValue = items[k];
299+
if (mapFn) {
300+
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
301+
} else {
302+
A[k] = kValue;
303+
}
304+
k += 1;
305+
}
306+
// 18. Let putStatus be Put(A, "length", len, true).
307+
A.length = len;
308+
// 20. Return A.
309+
return A;
310+
};
311+
}());
312+
}

src/ts/types.d.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,52 @@ interface PromiseExecutor<T> {
77
}
88

99
interface Promise<T> {
10-
then<NextT>(fulfilled?:(v:T)=>Promise<NextT>, rejected?:(err:any)=>Promise<NextT>):Promise<NextT>;
11-
// variants of then that support functor map are not provided, instead map here is
12-
// and is monkeypatched in in shims.ts\
13-
map<NextT>(fn:(v:T) => NextT):Promise<NextT>;
10+
then<NextT>(fulfilled?:(v:T)=>NextT|Promise<NextT>,
11+
rejected?:(err:any)=>NextT|Promise<NextT>):Promise<NextT>;
1412
'catch'(handle:(err:any) => any): any;
1513
}
1614

1715
interface PromiseStatic {
1816
new<T> (ex:PromiseExecutor<T>): Promise<T>;
17+
18+
resolve<T>(v:T|Promise<T>): Promise<T>;
19+
reject<T>(v:T|Promise<T>): Promise<T>;
20+
1921
all<T>(ps:Promise<T>[]): Promise<T[]>;
20-
of<T>(v:T): Promise<T>;
22+
race<T>(ps:Promise<T>[]): Promise<T[]>;
23+
2124
}
2225

2326
declare var Promise: PromiseStatic;
27+
28+
29+
// snaffled from ts es6.d.ts on github,
30+
// minus support for itereables
31+
interface ArrayLike<T> {
32+
length: number;
33+
[n: number]: T;
34+
}
35+
36+
37+
38+
interface ArrayConstructor {
39+
/**
40+
* Creates an array from an array-like object.
41+
* @param arrayLike An array-like object to convert to an array.
42+
* @param mapfn A mapping function to call on every element of the array.
43+
* @param thisArg Value of 'this' used to invoke the mapfn.
44+
*/
45+
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
46+
47+
/**
48+
* Creates an array from an array-like object.
49+
* @param arrayLike An array-like object to convert to an array.
50+
*/
51+
from<T>(arrayLike: ArrayLike<T>): Array<T>;
52+
53+
/**
54+
* Returns a new array from a set of elements.
55+
* @param items A set of elements to include in the new array object.
56+
*/
57+
of<T>(...items: T[]): Array<T>;
58+
}

0 commit comments

Comments
 (0)