PageSourceSearch

https://thestlbrowns.com/browns.min.js

js thestlbrowns.com collected 2026-10-02 09:55:59 UTC 677,651 bytes, 17,002 lines download raw bytes

1(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(require,module,exports){
2
3var Config = {
4
5	// cdn: 'path to your cdn server goes here',
6	cdn: '/',
7
8	fonts: {
9		BRANDON: "'Brandon Grotesque Regular', sans-serif",
10		BRANDONBLACK: "'Brandon Grotesque Black', sans-serif"
11	},
12
13	colors: {
14		ORANGE: "#f15c28",
15		BROWN: "#44312e",
16		BASEUI: 'rgba(195, 77, 36, 0.75)'
17	},
18
19	easing: {
20		MAIN: "easeOutCubic"
21	}
22}
23
24module.exports = Config;
25
26},{}],2:[function(require,module,exports){
27var Data = {
28
29	navigation: {
30
31		sections: [
32			{
33				key: "history",
34				title: "History",
35				url: "#/history"
36			},
37			{
38				key: "players",
39				title: "Players",
40				url: "#/players"
41			},
42			{
43				key: "about",
44				title: "About",
45				url: "#/about"
46			},
47			{
48				key: "membership",
49				title: "Membership",
50				url: "https://membership.thestlbrowns.com"
51			},
52			{
53				key: "merchandise",
54				title: "Merchandise",
55				url: "https://membership.thestlbrowns.com/stl-browns-shop/"
56			},
57			{
58				key: "gallery",
59				title: "Gallery",
60				url: "https://membership.thestlbrowns.com/gallery/"
61			},
62			{
63				key: "popflies",
64				title: "Popflies",
65				url: "https://membership.thestlbrowns.com/popflies/"
66			},
67			{
68				key: "events",
69				title: "Events",
70				url: "https://membership.thestlbrowns.com/events/"
71			},
72			{
73				key: "blog",
74				title: "Blog",
75				url: "https://membership.thestlbrowns.com/blog/"
76			},
77			{
78				key: "contact",
79				title: "Contact Us",
80				url: "https://membership.thestlbrowns.com/contact-us"
81			}
82
83
84			
85		],
86
87		social: [
88			{
89				key: "twitter",
90				title: "Twitter",
91				url: "https://twitter.com/Stl_browns",
92				ogImage: "",
93				ogDesc: ""
94			},
95			{
96				key: "facebook",
97				title: "Facebook",
98				url: "https://www.facebook.com/SaintLouisBrowns",
99				ogImage: "",
100				ogDesc: ""
101			},
102			{
103				key: "youtube",
104				title: "YouTube",
105				url: "https://www.youtube.com/user/OfficialSTLBrowns",
106				ogImage: "",
107				ogDesc: ""
108			}
109		],
110
111	},
112
113	historySection: {
114
115		title: "History",
116
117		sections: [
118
119			{
120				key: "the-early-years",
121				title: "The Early Years",
122				overviewImage: "the-early-years-index.jpg",
123				hero: {
124					image: "bg-the-early-years.jpg",
125					coverImage: "cover-the-early-years.png"
126				},
127				dates: {
128					from: 1902,
129					to: 1922
130				},
131				overlayData: {
132					"ty-cobb": {
133						title: "The Ty Cobb Scandal",
134						body: "<p>Ty Cobb was the almost-certain winner for the 1910 AL batting title. So certain, in fact, that he took the last day of the season off. Nap Lajoie, hardly behind by a hair, saw an opportunity — and so did Browns manager Jack O&rsquo;Connor, who happened to have it out for Cobb. O&rsquo;Connor ordered his third baseman to play deep on the grass for Lajoie, putting a perfect game well within reach. It was all Lajoie needed to surpass Cobb. In the end, Lajoie reached his last base on an error, giving Cobb the title he righteously earned. O&rsquo;Connor, and coach Harry Howell, who tried to bribe the official scorer out of the call, were fired from the Browns and never returned to the game.</p><p>Cobb&rsquo;s season was reinvestigated 70 years later. Sporting News historian Paul McFarlane found that he&rsquo;d been mistakenly credited for 2 hits — a difference that would&rsquo;ve given Lajoie the clear lead. Yet, the baseball commissioner at the time refused to strip Cobb of his honor, keeping Cobb&rsquo;s 9-season title streak in tact.</p>"
135					},
136					"almost": {
137						title: "6½ Games Out",
138						body: "<p>Years 2 through 6 weren&rsquo;t the Browns&rsquo; finest. They nearly hit 100 losses in 1905, but came back with a winning season (76-73) in 1906. Climbing out of the slump, the 1908 Browns were reasonably in the running for the pennant. They finished in 4th place, just 6 and a half games out of first.</p>"
139					}
140				}
141			},
142
143			{
144				key: "the-bottom-dwellers",
145				title: "The Bottom Dwellers",
146				overviewImage: "the-bottom-dwellers-index.jpg",
147				hero: {
148					image: "bg-the-bottom-dwellers.jpg",
149					coverImage: "cover-the-bottom-dwellers.png"
150				},
151				dates: {
152					from: 1926,
153					to: 1941
154				},
155				overlayData: {
156					"dewitt": {
157						title: "Bill DeWitt, Sr. (1902 &ndash; 1982)",
158						body: "<p>After the Browns moved to Baltimore, DeWitt headed north. He was the assistant general manager of the New York Yankees from 1954 to 1958, then served as president and GM of the Detroit Tigers from 1959 to 1960.</p><p>His third move had a bit more staying power. He was GM of the Cincinnati Reds from 1960 to 1966. He became sole owner and led them to pennant victory in 1961, built up a productive farm system, and maintained the team&rsquo;s status as a serious contender throughout his tenure.</p><p>DeWitt sold the Reds in 1966. Regardless, DeWitt was still credited for drafting, developing and trading for the players who&rsquo;d become the league-dominating &ldquo;Big Red Machine&rdquo;
158 of the 1970s.</p><p>For his final run, he sat as chairman of the Chicago White Sox from 1975-1981, working once again with the unforgettable Bill Veeck.</p><p>Baseball is a continued tradition in the DeWitt family. His son, William DeWitt, Jr., is the principal owner and managing partner of the St. Louis Cardinals. His grandson, William DeWitt, III, is the Cardinals&rsquo; president.</p>"
159					}
160				}
161			},
162
163			{
164				key: "the-war-years",
165				title: "The War Years",
166				overviewImage: "the-war-years-index.jpg",
167				hero: {
168					image: "bg-the-war-years.jpg",
169					coverImage: "cover-the-war-years.png"
170				},
171				dates: {
172					from: 1942,
173					to: 1946
174				}
175			},
176
177			{
178				key: "the-bill-veeck-era",
179				title: "The Bill Veeck Era",
180				overviewImage: "the-bill-veeck-era-index.jpg",
181				hero: {
182					image: "bg-the-veeck-era.jpg",
183					coverImage: "cover-the-veeck-era.png"
184				},
185				dates: {
186					from: 1949,
187					to: 1953
188				},
189				overlayData: {
190					"veeck": {
191						title: "Bill Veeck (1914 &ndash; 1986)",
192						body: "<p>After the St. Louis Browns, Bill Veeck licked his wounds, and returned to baseball again. When the White Sox won their first pennant in 40 years (1959), Bill Veeck was pulling the strings behind the scenes.</p><p>He had to sell his share of the White Sox in 1961 due to poor health, and briefly held down a commentating gig before disappearing from baseball for 14 years. In 1975, Veeck bought the White Sox and became the club&rsquo;s sole proprietor. He was back in the game, and back to his old clever ways.</p><p>He famously had Harry Caray sing &ldquo;Take Me Out to the Ball Game&rdquo; during the 7th-inning stretch. He offered fans free admission after the White Sox were defeated 10-2 on Opening Day in 1979. He held Disco Demolition Night, which ended in a riot at Comiskey Park and a forfeit to the Tigers.</p><p>When the free agent era arrived, Veeck couldn&rsquo;t keep up financially, so he sold the White Sox in early 1981. But he didn&rsquo;t exit the game entirely. Fans spotted him frequently at Wrigley Field, cheering on the Cubs, as he&rsquo;d done in his childhood.</p><p>Veeck was inducted to the Hall of Fame in 1991, five years after his death. He earned this recognition not solely for his wild promotions, but for the lasting and positive impact his approach had on the game. If it weren&rsquo;t for Veeck, baseball might not be the game we know and love today.</p>"
193					}
194				}
195			}
196		]
197	},
198
199	players: {
200
201		title: "Players",
202
203		players: [
204
205			{
206			  key: "clint-courtney",
207			  firstName: "Clint",
208			  lastName: "Courtney",
209			  url: "http://www.baseball-reference.com/players/c/courtcl01.shtml",
210			  bio: "<p>Listed at 5&rsquo; 8&rdquo; and 180 pounds, Courtney was an American League catcher whose pugnacity and timely base hits made headlines in the 1950s. Fiercely combative, he played his position under unusual handicaps. A natural left-hander, he taught himself to use his right arm, and he also was myopic, being widely considered as the first Major League catcher to wear eyeglasses. On July 16, 1953, Courtney entered the record books when the Browns tied, by then, a Major League mark with three successive home runs during the first inning of an 8–6 victory over the Yankees</p>",
211			  details: {
212			    position: "C",
213			    bats: "Left",
214			    arm: "Right",
215			    height: {
216			      feet: 5,
217			      inches: 8
218			    },
219			    weight: 180,
220			    city: "Hall Summit, LA",
221			    born: {
222			      year: 1927,
223			      month: 5,
224			      day: 16
225			    }
226			  }
227			},
228
229			{
230			  key: "les-moss",
231			  firstName: "Les",
232			  lastName: "Moss",
233			  url: "http://www.baseball-reference.com/players/m/mossle01.shtml",
234			  bio: "<p>Les Moss platooned alongside left-handed-hitting catcher Jake Early, producing a .157 batting average in 96 games during the 1947 season. He caught the majority of the games for the Browns in 1948 while his hitting improved substantially, with a .257 average along with 14 home runs and 46 runs batted in. In 1949, the Browns acquired 24-year-old Sherm Lollar from the New York Yankees and, Moss became the second string catcher. Moss&rsquo; hitting continued to improve with a .291 average and an impressive .399 on-base percentage.</p>",
235			  details: {
236			    position: "C",
237			    bats: "Right",
238			    arm: "Right",
239			    height: {
240			      feet: 5,
241			      inches: 11
242			    },
243			    weight: 205,
244			    city: "Tulsa, OK",
245			    born: {
246			      year: 1925,
247			      month: 5,
248			      day: 14
249			    }
250			  }
251			},
252
253			{
254			  key: "heinie-manush",
255			  firstName: "Heinie",
256			  lastName: "Manush",
257			  url: "http://www.baseball-reference.com/players/m/manushe01.shtml",
258			  bio: "<p>Henry Emmett Manush, nicknamed &ldquo;Heinie,&rdquo; was an American baseball outfielder. On December 13, 1927, the Tigers traded Manush and first baseman Lu Blue to the St. Louis Browns in exchange for outfielder Harry Rice, pitcher Elam Vangilder, and a player to be named later. The trade was promptly criticized as being one-sided in favor of St. Louis, and proved as much when Manush had an outstanding 1928 season for the Browns. Manu
258sh appeared in all 154 games as the Browns' starting left fielder in 1928 and compiled a .378 batting average, narrowly missing a second batting title to Goose Goslin who hit .379, one point higher than Manush.</p><p>The battle for the batting title was the closest in 18 years, and Manush, who appeared in 19 more games than Goslin, led the league with 241 hits, 68 more than Goslin. Manush also led the American League in 1928 with 241 hits and 47 doubles and finished among the league leaders with 367 total bases (second behind Babe Ruth), 20 triples (second), a 6.8 offensive wins above replacement rating (third behind Ruth and Lou Gehrig), 80 extra base hits (third behind Ruth and Gehrig), a .575 slugging percentage (fourth), and 108 RBIs (fourth). He helped the Browns improve by 23 wins from a 59-94 record in 1927 to an 82-72 record in 1928. He also finished second behind Mickey Cochrane in close voting for the 1928 American League Most Valuable Player award, with Cochrane garnering 53 vote points to 51 for Manush.</p>",
259			  details: {
260			    position: "LF",
261			    bats: "Left",
262			    arm: "Left",
263			    height: {
264			      feet: 6,
265			      inches: 1
266			    },
267			    weight: 200,
268			    city: "Tuscumbia, AL",
269			    born: {
270			      year: 1901,
271			      month: 7,
272			      day: 20
273			    }
274			  }
275			},
276
277			{
278			  key: "goose-goslin",
279			  firstName: "Goose",
280			  lastName: "Goslin",
281			  url: "http://www.baseball-reference.com/players/g/gosligo01.shtml",
282			  bio: "<p>Leon Allen &ldquo;Goose&rdquo; Goslin was a left fielder in Major League Baseball known for his powerful left-handed swing and dependable clutch hitting. He played 18 seasons with the St. Louis Browns. He was inducted into the Baseball Hall of Fame in 1968. The 1928 batting title was not decided until the last day of the season.</p><p>Goslin and Heinie Manush of the St. Louis Browns were tied going into the final game, and the Senators and Browns played each other in the final game. Goslin was leading Manush when his turn came to bat in the ninth inning. If Goslin made an out, he would lose the batting crown. In 101 games for the Browns, Goslin had 30 home runs, 100 RBI, and 62 extra base hits. Goslin had another solid year for the Browns in 1931, batting .328 with a career-high 42 doubles, 76 extra base hits and 105 RBI.</p>",
283			  hallOfFame: true,
284			  details: {
285			    position: "LF",
286			    bats: "Left",
287			    arm: "Right",
288			    height: {
289			      feet: 5,
290			      inches: 11
291			    },
292			    weight: 185,
293			    city: "Salem, NJ",
294			    born: {
295			      year: 1900,
296			      month: 10,
297			      day: 16
298			    }
299			  }
300			},
301
302			{
303			  key: "eddie-plank",
304			  firstName: "Eddie",
305			  lastName: "Plank",
306			  url: "http://www.baseball-reference.com/players/p/planked01.shtml",
307			  bio: "<p>Edward Stewart Plank, nicknamed &ldquo;Gettysburg Eddie,&rdquo; was an American professional baseball player. A pitcher, Plank played in Major League Baseball for the St. Louis Browns in 1916 and 1917. When the Federal League folded, Plank applied for free agency but was declared to belong to the St. Louis Browns for 1916. In September of that year, Plank predicted that he might be able to pitch ten more seasons, saying, &ldquo;I don&rsquo;t know whether it is that I have more on the ball this season than I had in other years, but at any rate I feel that I have just as much stuff as I ever did.&rdquo;</p>",
308			  hallOfFame: true,
309			  details: {
310			    position: "P",
311			    bats: "Left",
312			    arm: "Left",
313			    height: {
314			      feet: 5,
315			      inches: 11
316			    },
317			    weight: 175,
318			    city: "Gettysburg, PA",
319			    born: {
320			      year: 1875,
321			      month: 8,
322			      day: 31
323			    }
324			  }
325			},
326
327			{
328			  key: "george-stone",
329			  firstName: "George",
330			  lastName: "Stone",
331			  url: "http://www.baseball-reference.com/players/s/stonege01.shtml",
332			  bio: "<p>Nicknamed Silent George, he was a left fielder in Major League Baseball who played for the St. Louis Browns from 1905–1910. Stone batted and threw left-handed. He was the 1906 American League batting champion. In a seven-season career, Stone posted a .301 batting average with 23 home runs and 268 RBI in 848 games played.</p>",
333			  details: {
334			    position: "LF",
335			    bats: "Left",
336			    arm: "Left",
337			    height: {
338			      feet: 5,
339			      inches: 9
340			    },
341			    weight: 175,
342			    city: "Lost Nation, IA",
343			    born: {
344			      year: 1876,
345			      month: 9,
346			      day: 3
347			    }
348			  }
349			},
350
351			{
352			  key: "wayne-bromley-wright",
353			  firstName: "Wayne Bromley &ldquo;Rasty&rdquo;",
354			  lastName: "Wright",
355			  url: "http://www.baseball-reference.com/players/w/wrighra02.shtml",
356			  bio: "<p>Wayne Bromley &ldquo;Rasty&rdquo; Wright was a professional baseball pitcher. He played all or part of five seasons in Major League Baseball for the St. Louis Browns between 1917 and 1923.</p>",
357			  details: {
358			    position: "P",
359			    bats: "Right",
360			    arm: "Right",
361			    height: {
362			      feet: 5,
363			      inches: 11
364			    },
365			    weight: 160,
366			    city: "Ceredo, WV",
367			    born: {
368			      year: 1895,
369			      month: 11,
370			      day: 5
371			    }
372			  }
373			},
374
375			{
376			  key: "rube-waddell",
377			  firstName: "Rube",
378			  lastName: "Waddell",
379			  url: "http://www.baseball-reference.com/players/w/wadderu01.shtml",
380			  bio: "<p>George Edward &ldquo;Rube&rdquo; Waddell was an American southpaw pitcher in Major League Baseball (MLB). In a career spanning 13 years, he played for the St. Louis Browns (1908–10) in the American League. Born in Bradford, Pennsylvania, Waddell was elected to the Baseball Hall of Fame in 1946. Born in 1876 outside of Bradford, Pennsylvania, Waddell grew up in the country. Biographer Alan Levy writes that Waddell was &ldquo;a decidedly different sort of child.&rdquo; At the age of three, he wandered over to a local fire station and stayed for several days.
380</p><p>Waddell did not attend school very often, but he was considered to be literate. He strengthened his arm as a child by throwing rocks at birds he encountered while plowing the family's land. He also worked on mining and drilling sites as a youngster, which helped his conditioning. Waddell was a remarkably dominant strikeout pitcher in an era when batters mostly slapped at the ball to get singles. He had an excellent fastball, a sharp-breaking curve, a screwball, and superb control (his strikeout-to-walk ratio was almost 3-to-1). He led the major leagues in strikeouts for six consecutive years. </p>",
381			  hallOfFame: true,
382			  details: {
383			    position: "P",
384			    bats: "Right",
385			    arm: "Left",
386			    height: {
387			      feet: 6,
388			      inches: 1
389			    },
390			    weight: 196,
391			    city: "Bradford, PA",
392			    born: {
393			      year: 1876,
394			      month: 10,
395			      day: 13
396			    }
397			  }
398			},
399
400			{
401			  key: "rollie-stiles",
402			  firstName: "Rollie",
403			  lastName: "Stiles",
404			  url: "http://www.baseball-reference.com/players/s/stilero01.shtml",
405			  bio: "<p>Rolland Mays Stiles was an American right-handed pitcher in Major League Baseball who played for the St. Louis Browns from 1930 to 1933. Born in Ratcliff, Arkansas, he batted and threw right-handed, and was 9–14 with an earned run average of 5.92 in his three seasons. Rollie attended Southeastern State Teachers College. His first game in the major leagues was on June 19, 1930, and his last game was October 1, 1933. Stiles&rsquo; nicknames when playing baseball were &ldquo;Leapin&rsquo; Lena,&rdquo; &ldquo;Lena,&rdquo; and &ldquo;Rollie,&rdquo; all typical of how he signed autographs for baseball fans. He died in his sleep at age 100 on July 22, 2007 at the Bethesda Southgate Nursing Home in St. Louis. He was the last living person to have pitched to Babe Ruth.</p>",
406			  details: {
407			    position: "P",
408			    bats: "Right",
409			    arm: "Right",
410			    height: {
411			      feet: 6,
412			      inches: 1
413			    },
414			    weight: 180,
415			    city: "Ratcliff, AR",
416			    born: {
417			      year: 1906,
418			      month: 11,
419			      day: 17
420			    }
421			  }
422			},
423
424			{
425			  key: "dale-long",
426			  firstName: "Dale",
427			  lastName: "Long",
428			  url: "http://www.baseball-reference.com/players/l/longda02.shtml",
429			  bio: "<p>A native of Springfield, Missouri, Long turned down an offer from the Green Bay Packers to play football, opting instead to play baseball. Long spent six seasons in the minor leagues, playing for five different organizations before he debuted with the Pittsburgh Pirates in 1951, ending that season with the St. Louis Browns. </p>",
430			  details: {
431			    position: "1B",
432			    bats: "Left",
433			    arm: "Left",
434			    height: {
435			      feet: 6,
436			      inches: 4
437			    },
438			    weight: 205,
439			    city: "Springfield, MO",
440			    born: {
441			      year: 1926,
442			      month: 2,
443			      day: 6
444			    }
445			  }
446			},
447
448			{
449			  key: "bob-dillinger",
450			  firstName: "Bob",
451			  lastName: "Dillinger",
452			  url: "http://www.baseball-reference.com/players/d/dillibo01.shtml",
453			  bio: "<p>Born in Glendale, California, Dillinger attended the University of Idaho in Moscow and played football for the Vandals, but broke his collarbone as a freshman in 1936 and was injured again as a sophomore; he left the school in the spring of 1938. He was signed by the Browns as an amateur free agent in 1939.</p>",
454			  details: {
455			    position: "3B",
456			    bats: "Right",
457			    arm: "Right",
458			    height: {
459			      feet: 5,
460			      inches: 11
461			    },
462			    weight: 170,
463			    city: "Glendale, CA",
464			    born: {
465			      year: 1918,
466			      month: 9,
467			      day: 17
468			    }
469			  }
470			},
471
472			{
473				key: "rick-ferrell",
474				firstName: "Rick",
475				lastName: "Ferrell",
476				url: "http://www.baseball-reference.com/players/f/ferreri01.shtml",
477				bio: "<p>Rick Ferrell cut his teeth as catcher at home — his six brothers all wanted to be pitchers. It paid off. With a knack for catching knuckleballs and picking off stolen base attempts, this 8-time All-Star* became known as one of the best catchers in the game during the &lsquo;30s and &lsquo;40s. His skills at the plate weren&rsquo;t just limited to catching. Among catchers with 3,000 at-bats, Ferrell&rsquo;s .378 career on-base percentage is 8th all-time, and 4th among the 13 major league Hall of Fame catchers. Ferrell played for the Browns twice during his peak: from 1929-1933, and from 1941-1943.</p><p>As for his brothers? Only one of them, Wes, made it to the majors. When asked how it was to play against his brother, Rick said, &ldquo;We were brothers off the field, but there was no love lost on it. We fought like cats and dogs. Wes was always trying to strike me out, and meantime, I was always trying to hit a home run off him.&rdquo;</p><p>*His eighth appearance never actually happened. The 1945 All-Star Game was cancelled due to wartime travel restrictions.</p>",
478				hallOfFame: true,
479				details: {
480					position: "C",
481					bats: "Right",
482					arm: "Right",
483					height: {
484						feet: 5,
485						inches: 10
486					},
487					weight: 160,
488					city: "Durham, NC",
489					born: {
490						year: 1905,
491						month: 10,
492						day: 12
493					}
494				}
495			},
496
497			{
498				key: "bobby-wallace",
499				firstName: "Bobby",
500				lastName: "Wallace",
501				url: "http://www.baseball-reference.com/players/w/wallabo01.shtml",
502				bio: "<p>Bobby Wallace holds the record for longest career by a player who never reached the World Series. But that&rsquo;s not the only reason he&rsquo;s noteworthy. He was a top-10 RBI leader for eight seasons in the peak of his career. He also holds the American League record for most chances accepted in one game: 17 (against the Boston Red Sox on June 10, 1902).</p><p>What he lacked in height, he made up in his mental fortitude. Wallace reflected, &ldquo;As more speed afoot was constantly demanded for big league ball, I noticed the many infield bounders which the runner beat to first only by the thinnest fractions of a second. I also noted that the old-time three-phase movement — fielding a ball, coming erect for a toss and throwing to first — wouldn't do on certain hits with fast men&hellip; It was plain that the stop and toss had to be combined into a continuous movement.&rdquo;</p><p>In 1911, Pittsburgh Pirates owner Barney Dreyfuss declared, &ldquo;The best player in the American League, the only man I would get if I could, plays on a tail-end team, and few people pay any attention to him. I mean Bobby Wallace of St. Louis. I wish I had him.&rdquo; Indeed, this Hall of Famer might be the greatest defensive shortstop of his generation.</p>",
503				hallOfFame: true,
504				cardinalsPlayer: true,
505				details: {
506					position: "SS, 3B",
507					bats: "Right",
508					arm: "Right",
509					height: {
510						feet: 5,
511						inches: 8
512					},
513					weight: 170,
514					city: "Pittsburgh, PA",
515					born: {
516						year: 1873,
517						month: 11,
518						day: 4
519					}
520				}
521			},
522
523			{
524				key: "dizzy-dean",
525				firstName: "Dizzy",
526				lastName: "Dean",
527				url: "http://www.baseball-reference.com/players/d/deandi01.shtml",
528				bio: "<p>From 1932 to 1937, Dizzy Dean was arguably the best pitcher in all of baseball. But in the 1937 All-Star game, a line drive back to the mound fractured Dizzy&rsquo;s toe, or as he would say &ldquo;Fractured, hell, the damn thing's broken!&rdquo; Dizzy was never the same man on the mound — a change in mechanics to deal with the toe injury led to an arm injury.</p><p>Thankfully, when it came to his colorful use of the English language, he hadn&rsquo;t changed a bit, as he quickly transitioned to a career in broadcasting. His wit and perfectly placed malapropisms earned him a large following as the radio voice for the Browns. Oddly, this led him to one more appearance on the mound. The pitching was so bad during the Browns&rsquo; lowly 1947 season, Dizzy would often remark in his broadcasts that he could do better. Six years removed from throwing in a game, Dizzy left his booth to be the Browns&rsquo; starting pitcher for the last game of the year. He pitched four shutout innings, and even got a hit, before leaving the game with a pulled muscle — the final injury of his playing career.</p>",
529				hallOfFame: true,
530				cardinalsPlayer: true,
531				details: {
532					position: "P",
533					bats: "Right",
534					arm: "Right",
535					height: {
536						feet: 6,
537						inches: 2
538					},
539					weight: 182,
540					city: "Lucas, AR",
541					born: {
542						year: 1910,
543						month: 1,
544						day: 16
545					}
546				}
547			},
548
549			{
550				key: "george-sisler",
551				firstName: "George",
552				lastName: "Sisler",
553				url: "http://www.baseball-reference.com/players/s/sislege01.shtml",
554				bio: "<p>Who is George Sisler? Unquestionably, the greatest player in St. Louis Browns&rsquo; history. Once considered an equal to the likes of Ruth, Cobb and Hornsby, &ldquo;The Sizzler&rdquo; won the AL batting title twice (hitting over .400 both times), led the AL in stolen bases four times, and held the single-season hit record (257) for 84 years. He is also regarded as one of the best defensive first basemen to play the game.</p><p>Today, he&rsquo;s quite possibly the best player most baseball fans have never heard of. But greatness has a way of being rediscovered. Born 6,000 miles away and 80 years later, Ichiro Suzuki broke Sisler&rsquo;
554s single-season hit record in 2004. He later laid flowers on Sisler&rsquo;s grave to honor him. With the symbolic tip of his cap, Suzuki reawakened fans to one of baseball&rsquo;s greatest, nearly forgotten treasures.</p>",
555				hallOfFame: true,
556				details: {
557					position: "1B",
558					bats: "Left",
559					arm: "Left",
560					height: {
561						feet: 5,
562						inches: 11
563					},
564					weight: 180,
565					city: "Manchester, OH",
566					born: {
567						year: 1893,
568						month: 3,
569						day: 24
570					}
571				}
572			},
573
574			{
575				key: "ken-williams",
576				firstName: "Ken",
577				lastName: "Williams",
578				url: "http://www.baseball-reference.com/players/w/willike01.shtml",
579				bio: "<p>First player to poke two home runs in one inning. First to hit 30 out of the park and steal 30 bases in the same season. A six-game streak with a tater in each. League leader in homers and ribbies. Ken Williams didn&rsquo;t compile these stats over the course of a long career — it all happened in 1922. Despite the offensive prowess, Williams and the &lsquo;22 Browns (the organization&rsquo;s best club) still fell a game and a half short of the AL pennant.</p>",
580				details: {
581					position: "LF",
582					bats: "Left",
583					arm: "Right",
584					height: {
585						feet: 6,
586						inches: 0
587					},
588					weight: 170,
589					city: "Grants Pass, OR",
590					born: {
591						year: 1890,
592						month: 6,
593						day: 28
594					}
595				}
596			},
597
598			{
599				key: "baby-doll-jacobson",
600				firstName: "Baby Doll",
601				lastName: "Jacobson",
602				url: "http://www.baseball-reference.com/players/j/jacobba01.shtml",
603				bio: "<p>Baby Doll Jacobson rivaled The Babe in stats and stature. Batting better than .300 for 7 consecutive seasons (1919-1925), he was no small threat to his opponents.</p><p>So, why the nickname? At a game in 1912, the band was playing &ldquo;Oh, You Beautiful Doll&rdquo; as Jacobson walked up to the plate. First pitch, he smoked the ball halfway to China. A lady shouted from stands, &ldquo;You must be that beautiful doll they were talking about.&rdquo; The rest is history.</p><p>After the Browns: &ldquo;Although he never received more than a passing glance in the Hall of Fame voting, Jacobson's credentials are superior to many of the old-timers who have been enshrined.&rdquo; &mdash; written in The Sporting News following Jacobson&rsquo;s death in 1977. Traded to the Boston Red Sox in 1926, Jacobson&rsquo;s .981 fielding percentage that season was second among AL center fielders. After short stints with the Indians, the Athletics and a few minor league teams, Jacobson left baseball and spent the remainder of his years on his Illinois farm, not too far from where he grew up.</p>",
604				details: {
605					position: "CF",
606					bats: "Right",
607					arm: "Right",
608					height: {
609						feet: 6,
610						inches: 3
611					},
612					weight: 215,
613					city: "Cable, IL",
614					born: {
615						year: 1890,
616						month: 8,
617						day: 16
618					}
619				}
620			},
621
622			{
623				key: "jack-tobin",
624				firstName: "Jack",
625				lastName: "Tobin",
626				url: "http://www.baseball-reference.com/players/t/tobinja01.shtml",
627				bio: "<p>To his friends and the newspapers in St. Louis, he was Johnny. But in the record books, he was Jack. To teammate and legend-in-the-making George Sisler, he was &ldquo;one of the best leadoff men I ever saw&hellip; He was fast and a good outfielder with a strong throwing arm and, above all, he was the best drag-bunter anyone ever saw.&rdquo;</p><p>Tobin didn&rsquo;t see much playing time in his first year with the Browns (1916). However, he did face his former team, the Federal League&rsquo;s St. Louis Terriers, in a so-called City Series. They lost, but Tobin and the Browns swept the Cardinals in the City Series two years later.</p><p>After a productive trip to the Pacific Coast League, Tobin was back on the Browns by 1918. His best run was from 1919 to 1923. Tobin batted well over .300 every year, topping out at .352, and roping 13 homers two seasons in a row. He led the league in 1921 with 18 triples, and was second in runs scored with 132. When he dipped a point below .300 in 1924, legend has it that he had his teeth removed.</p><p>
627In 1925, Tobin was out-hit by rightfielder Harry Rice, and lost his starting privileges. He was traded to the Washington Senators before the start of the 1926 season.</p>",
628				details: {
629					position: "RF",
630					bats: "Left",
631					arm: "Left",
632					height: {
633						feet: 5,
634						inches: 8
635					},
636					weight: 142,
637					city: "St. Louis, MO",
638					born: {
639						year: 1892,
640						month: 5,
641						day: 4
642					}
643				}
644			},
645
646			{
647				key: "pete-gray",
648				firstName: "Pete",
649				lastName: "Gray",
650				url: "http://www.baseball-reference.com/players/g/graype01.shtml",
651				bio: "<p>Before there was Jim Abbott, there was Pete Gray. At age six, Gray lost his right arm in a farming accident. But he never lost his determination to play ball. The natural righty learned to bat and throw left-handed to pursue his dream. After an MVP season in the minors, he was called up to play for the Browns in 1945. It was his only year in the majors; like so many two-handed players before him, Gray couldn't hit the off-speed pitch. Gray, more than anyone, knew his opportunity to play came about from depleted wartime rosters. While he himself couldn&rsquo;t serve, he honored veterans by visiting them at the hospital, becoming an inspiration for thousands of disabled servicemen returning from the war.</p>",
652				details: {
653					position: "OF",
654					bats: "Left",
655					arm: "Left",
656					height: {
657						feet: 6,
658						inches: 1
659					},
660					weight: 169,
661					city: "Nanticoke, PA",
662					born: {
663						year: 1915,
664						month: 3,
665						day: 6
666					}
667				}
668			},
669
670			{
671				key: "eddie-gaedel",
672				firstName: "Eddie",
673				lastName: "Gaedel",
674				url: "http://www.baseball-reference.com/players/g/gaedeed01.shtml",
675				bio: "<p>Normally, one plate appearance wouldn&rsquo;t leave a mark on the history of baseball. But normally, Eddie Gaedel wasn&rsquo;t up to bat. On August 19, 1951, as part of a trademark Bill Veeck promotional stunt, the 3-foot-7 Gaedel came to the plate to pinch hit. He wore the number ⅛ on a jersey made for Bill DeWitt&rsquo;s son. Four balls later, Gaedel achieved a career on-base percentage of 1.000. Even though his contract was voided by the league two days later, Gaedel&rsquo;s jersey still has a spot in the National Baseball Hall of Fame.</p><p>&ldquo;He was, by golly, the best damn midget who ever played big-league ball. He was also the only one.&rdquo; - Bill Veeck</p>",
676				details: {
677					position: "PH",
678					bats: "Right",
679					arm: "Left",
680					height: {
681						feet: 3,
682						inches: 7
683					},
684					weight: 65,
685					city: "Chicago, IL",
686					born: {
687						year: 1925,
688						month: 6,
689						day: 8
690					}
691				}
692			},
693
694			{
695				key: "ned-garver",
696				firstName: "Ned",
697				lastName: "Garver",
698				url: "http://www.baseball-reference.com/players/g/garvene01.shtml",
699				bio: "<p>In 1951, while the Browns lost 102 games, Ned Garver racked up 20 wins — the only pitcher in the majors to do so well for such a losing team, even to this day. He also led the American League in complete games (24) and was the starting pitcher for the All-Star game in Detroit. That same year, he earned (and clearly deserved) the highest salary on the team: a whopping $25,000.</p><p>Despite his triumphs on the mound, he never pitched in a World Series. Garver thought, &ldquo;If you played in a World Series, people get the impression that you were somewhat more of an outstanding player than if you never did. You're put in a kind of special category if you were on a pennant winning team.&rdquo;</p><p>Still, that didn&rsquo;t stop him from becoming a legend. Ted Williams, one of baseball&rsquo;s greatest hitters, said of Ned, &ldquo;He could throw anything up there and get me out.&rdquo;</p>",
700				details: {
701					position: "P",
702					bats: "Right",
703					arm: "Right",
704					height: {
705						feet: 5,
706						inches: 10
707					},
708					weight: 180,
709					city: "Ney, OH",
710					born: {
711						year: 1925,
712						month: 12,
713						day: 25
714					}
715				}
716			},
717
718			{
719				key: "satchel-paige",
720				firstName: "Satchel",
721				lastName: "Paige",
722				url: "http://www.baseball-reference.com/players/p/paigesa01.shtml",
723				bio: "<p>As the Cleveland Indians owner, Bill Veeck signed Satchel to his first major league contract in 1948, when Satchel was 42, making him the oldest rookie ever in the major leagues. After Veeck bought into the Browns in 1951, he signed Paige once again. In 1952, Paige had proved himself to be such an asset, he either started or came in for relief every three games. That same year, Paige represented the Browns in the All-Star Game, but didn&rsquo;t see any playing time, so Casey Stengel nominated him again for the 1953 team.</p><p>The selling of the Browns to Baltimore was the last of Paige&rsquo;s major league career, until he returned with the Kansas City Athletics in 1965. (He went back to the Negro Leagues in between.) Although his major league career was only 6 seasons, his name will be remembered forever.</p><p>&ldquo;If Satch and I were pitching on the same team, we&rsquo;d clinch the pennant by the fourth of July and go fishing until World Series time.&rdquo; &mdash;
723 Dizzy Dean</p>",
724				hallOfFame: true,
725				details: {
726					position: "P",
727					bats: "Right",
728					arm: "Right",
729					height: {
730						feet: 6,
731						inches: 3
732					},
733					weight: 180,
734					city: "Mobile, AL",
735					born: {
736						year: 1906,
737						month: 7,
738						day: 7
739					}
740				}
741			},
742
743			{
744				key: "vern-stephens",
745				firstName: "Vern",
746				lastName: "Stephens",
747				url: "http://www.baseball-reference.com/players/s/stephve01.shtml",
748				bio: "<p>With peers like Phil Rizzuto, Marty Marion, Pee Wee Reese and Johnny Pesky, Vern Stephens was part of a special crop of shortstops from the 1940s. While the legends of his peers have grown, the memory of Vern &ldquo;Junior&rdquo; Stephens has largely faded over time. It&rsquo;s a shame, because he just might have been the best of that bunch.</p><p>Growing up, Stephens was a slight kid, weighing in at just 100 lbs. But he built himself up, and soon became known for his power at the plate. An 8-time All-Star, 3-time RBI champ, and perennial MVP candidate, Stephens had an arm like a shotgun, and a trick knee that kept him from being drafted. History may have nearly forgotten him, but his stat lines will forever tell the story of one of the greatest power-hitting shortstops in baseball.</p>",
749				details: {
750					position: "SS, 3B",
751					bats: "Right",
752					arm: "Right",
753					height: {
754						feet: 5,
755						inches: 10
756					},
757					weight: 185,
758					city: "McAllister, NM",
759					born: {
760						year: 1920,
761						month: 23,
762						day: 10
763					}
764				}
765			},
766
767			{
768				key: "len-schulte",
769				firstName: "Len",
770				lastName: "Schulte",
771				url: "http://www.baseball-reference.com/players/s/schulle01.shtml",
772				bio: "<p>Len Schulte&rsquo;s big league debut was soggy. In his only appearance for the 1944 Browns, Schulte drew a walk in a rainy late September 4-1 loss to the Boston Red Sox. He saw less rain and more playing time the next season, appearing in 110 games at third-base.</p>",
773				details: {
774					position: "3B, 2B, SS",
775					bats: "Right",
776					arm: "Right",
777					height: {
778						feet: 5,
779						inches: 10
780					},
781					weight: 160,
782					city: "St. Charles, MO",
783					born: {
784						year: 1916,
785						month: 12,
786						day: 5
787					}
788				}
789			},
790
791			{
792				key: "george-caster",
793				firstName: "George",
794				lastName: "Caster",
795				url: "http://www.baseball-reference.com/players/c/castege01.shtml",
796				bio: "<p>After joining the Browns as a starting pitcher in 1941, George &ldquo;Ug&rdquo; Caster found his calling as a closer. &ldquo;I like to be in there when the going is tough, trying to save a game,&rdquo; Caster said. And save games he did — Caster led the American League in saves as he helped the Browns take the pennant in 1944.</p>",
797				details: {
798					position: "P",
799					bats: "Right",
800					arm: "Right",
801					height: {
802						feet: 6,
803						inches: 1
804					},
805					weight: 180,
806					city: "Colton, CA",
807					born: {
808						year: 1907,
809						month: 8,
810						day: 4
811					}
812				}
813			},
814
815			{
816				key: "frank-demaree",
817				firstName: "Frank",
818				lastName: "Demaree",
819				url: "http://www.baseball-reference.com/players/d/demarfr02.shtml",
820				bio: "<p>A veteran outfielder, Frank Demaree joined the Browns just before the start of the 1944 season. He played in 16 games before being released, going 0-for-3 in what would be his final major league appearance. Had he made it to the postseason, he would have been on the losing side of five different World Series throughout his career.</p>",
821				details: {
822					position: "OF",
823					bats: "Right",
824					arm: "Right",
825					cardinalsPlayer: true,
826					height: {
827						feet: 5,
828						inches: 11
829					},
830					weight: 185,
831					city: "Winters, CA",
832					born: {
833						year: 1910,
834						month: 6,
835						day: 10
836					}
837				}
838			},
839
840			{
841				key: "denny-galehouse",
842				firstName: "Denny",
843				lastName: "Galehouse",
844				url: "http://www.baseball-reference.com/players/g/galehde01.shtml",
845				bio: "<p>After two seasons with the Browns (1942-1943), Denny Galehouse left the team to help the war effort, working 6 days a week at a plant in Akron, Ohio. Midway through the &lsquo;44 season, the Browns persuaded Galehouse to be their &ldquo;Sunday pitcher.&rdquo; After his Saturday shift, he&rsquo;d take an overnight train to St. Louis, pitch the first game of the Sunday double-header, then go back to Akron. It soon became clear that the Browns were on their way to first place in the American League. Galehouse came back to the Browns full-time, helping them win the pennant and Game 1 of the World Series.</p><p>&ldquo;The World Series Cardinals had Stan Musial, Whitey Kurowski, Marty Marion, Walker Cooper, Mort Cooper&hellip; they had pretty much a big league team,&rdquo; Galehouse recalled. (Most major league teams, like the Browns, were made up of 4-F guys who weren&rsquo;t able to fight in the war.) &ldquo;They weren&rsquo;t an easy squad,&rdquo; he said. But that didn&rsquo;t stop him from getting the win.</p>",
846				details: {
847					position: "P",
848					bats: "Right",
849					arm: "Right",
850					height: {
851						feet: 6,
852						inches: 1
853					},
854					weight: 195,
855					city: "Marshallville, OH",
856					born: {
857						year: 1911,
858						month: 12,
859						day: 7
860					}
861				}
862			},
863
864			{
865				key: "hal-epps",
866				firstName: "Hal",
867				lastName: "Epps",
868				url: "http://www.baseball-reference.com/players/e/eppsha01.shtml",
869				bio: "<p>Hal Epps, known to some as &ldquo;The Reindeer,&rdquo; was one of just a handful of players to claim allegiance to both St. Louis teams. After a few years in the minors, 28 games with the Cardinals (in 1938 and 1940), and a tour in the South Pacific, Epps joined the Browns in 1943. Known for his speedy wheels and his dedication to making tough plays, Epps contributed greatly to the 9-game winning streak that helped the Browns win the 1944 AL pennant.</p>",
870				cardinalsPlayer: true,
871				details: {
872					position: "CF",
873					bats: "Left",
874					arm: "Left",
875					height: {
876						feet: 6,
877						inches: 0
878					},
879					weight: 175,
880					city: "Athens, GA",
881					born: {
882						year: 1914,
883						month: 3,
884						day: 26
885					}
886				}
887			},
888
889			{
890				key: "al-hollingsworth",
891				firstName: "Al",
892				lastName: "Hollingsworth",
893				url: "http://www.baseball-reference.com/players/h/hollial01.shtml",
894				bio: "<p>He was the pitcher they called &ldquo;Boots.&rdquo; 4 was not his lucky number — he came into Game 4 of the 1944 World Series in the 4th inning, 4 runs back, and never had the opportunity for a save. However, the following year, Boots brought home his second winning record of his Browns career and an ERA under 3.00.</p><p>After the Browns: Hollingsworth played his last game on September 22, 1946, as a member of the White Sox club, ending his professional playing career of 20 consecutive seasons (including time in the minors). He then became a manager for the St. Louis Cardinals and Cleveland Indians, a pitching coach for the Redbirds, and a scout for 4 major league teams.</p>",
895				details: {
896					position: "P",
897					bats: "Left",
898					arm: "Left",
899					height: {
900						feet: 6,
901						inches: 0
902					},
903					weight: 174,
904					city: "Cincinatti, OH",
905					born: {
906						year: 1908,
907						month: 2,
908						day: 25
909					}
910				}
911			},
912
913			{
914				key: "willis-hudlin",
915				firstName: "Willis",
916				lastName: "Hudlin",
917				url: "http://www.baseball-reference.com/players/h/hudliwi01.shtml",
918				bio: "<p>Nicknamed &ldquo;Ace,&rdquo; Willis Hudlin was known for his sinker. It must have been a good one, because four teams wanted it&hellip; in one season. In 1940, Ace played for four different clubs, a distinction he shares with only a handful of other MLB players. There&rsquo;s one achievement that&rsquo;s all his own, giving up Babe Ruth&rsquo;s 500th home run. Don&rsquo;t feel too bad for Ace, though, he won the game 6-5.</p>",
919				details: {
920					position: "P",
921					bats: "Right",
922					arm: "Right",
923					height: {
924						feet: 6,
925						inches: 0
926					},
927					weight: 190,
928					city: "Wagoner, OK",
929					born: {
930						year: 1906,
931						month: 5,
932						day: 23
933					}
934				}
935			},
936
937			{
938				key: "tom-hafey",
939				firstName: "Tom",
940				lastName: "Hafey",
941				url: "http://www.baseball-reference.com/players/h/hafeyto01.shtml",
942				bio: "<p>Tom &ldquo;Heave-O&rdquo; Hafey was born into a baseball family — his brother Bud and cousin Chick also played in the majors. While he had a rocket of an arm, his brief career skipped around a bit. After a season with the Giants in 1939, Hafey joined the Browns for 8 games in 1944. He played a game at first base, a game at third base, three games in left field, pinch hit four times, then said goodbye to baseball.</p>",
943				details: {
944					position: "3B, LF",
945					bats: "Right",
946					arm: "Right",
947					height: {
948						feet: 6,
949						inches: 1
950					},
951					weight: 180,
952					city: "Berkeley, CA",
953					born: {
954						year: 1913,
955						month: 7,
956						day: 12
957					}
958				}
959			},
960
961			{
962				key: "mike-kreevich",
963				firstName: "Mike",
964				lastName: "Kreevich",
965				url: "http://www.baseball-reference.com/players/k/kreevmi01.shtml",
966				bio: "<p>By the time he reached the Browns in 1943, 35-year-old Mike Kreevich had seen a lot: coal mines, the Great Depression, and both Chicago baseball teams. But in 1944, he saw something really special: a World Series. Sure, he struck out five times. But he still managed three doubles and a .231 average for the Series.</p>",
967				details: {
968					position: "CF",
969					bats: "Right",
970					arm: "Right",
971					height: {
972						feet: 5,
973						inches: 7
974					},
975					weight: 168,
976					city: "Mount Olive, IL",
977					born: {
978						year: 1908,
979						month: 10,
980						day: 6
981					}
982				}
983			},
984
985			{
986				key: "sig-jackuki",
987				firstName: "Sig",
988				lastName: "Jackuki",
989				url: "http://www.baseball-reference.com/players/j/jakucsi01.shtml",
990				bio: "<p>On the field and off, Big Sig Jakucki&rsquo;s story is as much of a roller coaster as the entirety of the Browns&rsquo; legacy. Ellis Clary recalls, &ldquo;He&rsquo;s a tough son of a bitch&hellip; but you couldn&rsquo;t help but like him if he was on your side. He was a fun guy, but gee, at night he&rsquo;d get a few belts and turn over a joint somewhere. No matter where he was, he&rsquo;d get in trouble.&rdquo;</p><p>Signed to the team in 1936, Jakucki&rsquo;s first year was a bust. Then, when World War II left the Browns lacking for players in 1944, they re-signed him. Jakucki not only went 13-9 that year, he pitched the last game of the season against the Yankees, helping the Browns clinch the pennant with a 5-2 win. Unfortunately, he went down fighting in a 5-1 loss in Game 4 of the World Series, giving up 4 runs before the 4th inning. Still, the Browns would never have gotten that far without him.</p>",
991				details: {
992					position: "P",
993					bats: "Right",
994					arm: "Right",
995					height: {
996						feet: 6,
997						inches: 2
998					},
999					weight: 198,
1000					city: "Camden, NJ",
1001					born: {
1002						year: 1909,
1003						month: 8,
1004						day: 20
1005					}
1006				}
1007			},
1008
1009			{
1010				key: "chet-laabs",
1011				firstName: "Chet",
1012				lastName: "Laabs",
1013				url: "http://www.baseball-reference.com/players/l/laabsch01.shtml",
1014				bio: "<p>Two home runs in back-to-back innings? That&rsquo;s a big deal for any player. But in a game that clinched the Browns&rsquo; only American League pennant, on the last day of the season? That&rsquo;s legendary. And that&rsquo;s the legend of Chet Laabs.</p>",
1015				details: {
1016					position: "OF",
1017					bats: "Right",
1018					arm: "Right",
1019					height: {
1020						feet: 5,
1021						inches: 8
1022					},
1023					weight: 175,
1024					city: "Milwaukee, WI",
1025					born: {
1026						year: 1912,
1027						month: 04,
1028						day: 30
1029					}
1030				}
1031			},
1032
1033			{
1034				key: "jack-kramer",
1035				firstName: "Jack",
1036				lastName: "Kramer",
1037				url: "http://www.baseball-reference.com/players/k/krameja01.shtml",
1038				bio: "<p>At the start of the 1943 season, Jack Kramer earned the Browns their 8th straight Opening Day victory. Just a week later, he claimed the 6th win of the team&rsquo;s 9-game streak — the last of which he also won. With an impressive 17-13 regular season record, Kramer no doubt helped the Browns earn the pennant. Yet, his most notable moment awaited him in the post-season: He pitched a victorious Game Three in that year&rsquo;s historic all-St. Louis World Series.</p><p>This three-time All-Star (1945-1947) kept the dugout in stitches with his Bugs Bunny impression and wicked wit, but he occasionally let his wild side get the best of him. In 1944, Indians player-manager Lou Boudreau came up to the plate. The dugout was talking smack behind him. Kramer had no qualms about giving Boudreau a fastball to the ribs. Kramer met him at the first-baseline with a warning: &ldquo;If you don&rsquo;t keep those guys on the bench quiet, I&rsquo;ll stick one in your ear the next time you come to bat.&rdquo;</p>",
1039				details: {
1040					position: "P",
1041					bats: "Right",
1042					arm: "Right",
1043					height: {
1044						feet: 6,
1045						inches: 2
1046					},
1047					weight: 190,
1048					city: "New Orleans, LA",
1049					born: {
1050						year: 1918,
1051						month: 1,
1052						day: 5
1053					}
1054				}
1055			},
1056
1057			{
1058				key: "gene-moore",
1059				firstName: "Gene",
1060				lastName: "Moore",
1061				url: "http://www.baseball-reference.com/players/m/moorege03.shtml",
1062				bio: "<p>Gene &ldquo;Rowdy&rdquo; Moore played 14 seasons in the majors, but it was number 13 that was especially lucky. The journeyman outfielder played for six different teams before joining the &lsquo;44 Browns, where he hit 13 doubles on the way to winning the American League pennant.</p>",
1063				cardinalsPlayer: true,
1064				details: {
1065					position: "RF",
1066					bats: "Left",
1067					arm: "Left",
1068					height: {
1069						feet: 5,
1070						inches: 11
1071					},
1072					weight: 175,
1073					city: "Lancaster, TX",
1074					born: {
1075						year: 1909,
1076						month: 26,
1077						day: 8
1078					}
1079				}
1080			},
1081
1082			{
1083				key: "bob-muncrief",
1084				firstName: "Bob",
1085				lastName: "Muncrief",
1086				url: "http://www.baseball-reference.com/players/m/muncrbo01.shtml",
1087				bio: "<p>Bob Muncrief pitched for the Browns for 9 seasons. In 1941, he almost — almost — ended DiMaggio&rsquo;s hitting streak at 35. Later, he helped the Browns fight their way to the 1944 American League pennant victory. He also played in the All-Star Game that same year.</p>",
1088				details: {
1089					position: "P",
1090					bats: "Right",
1091					arm: "Right",
1092					height: {
1093						feet: 6,
1094						inches: 2
1095					},
1096					weight: 190,
1097					city: "Madill, OK",
1098					born: {
1099						year: 1916,
1100						month: 1,
1101						day: 28
1102					}
1103				}
1104			},
1105
1106			{
1107				key: "tom-turner",
1108				firstName: "Tom",
1109				lastName: "Turner",
1110				url: "http://www.baseball-reference.com/players/t/turneto01.shtml",
1111				bio: "<p>Tom Turner broke into the bigs as a 23-year-old rookie. He was the Browns&rsquo; backstop in 1944, then went off to serve his country in WWII. Turner returned from service, but never returned to the majors. After a brief stint in the Pacific Coast League in 1946, he put down his lumber for good and retired among the timbers of the Pacific N
1111orthwest.</p>",
1112				details: {
1113					position: "C",
1114					bats: "Right",
1115					arm: "Right",
1116					height: {
1117						feet: 6,
1118						inches: 2
1119					},
1120					weight: 195,
1121					city: "Custer, OK",
1122					born: {
1123						year: 1916,
1124						month: 9,
1125						day: 8
1126					}
1127				}
1128			},
1129
1130			{
1131				key: "nels-potter",
1132				firstName: "Nels",
1133				lastName: "Potter",
1134				url: "http://www.baseball-reference.com/players/p/pottene01.shtml",
1135				bio: "<p>Nels Potter never shaved on days he took the mound. Whether it was due to his superstition or his stinky cheddar, Nels went 19-7 in 1944 regular season games. But for some reason, he shaved before his start in Game Two of the 1944 World Series — a game he should&rsquo;ve won. Despite the loss, Potter&rsquo;s 1944 season was still remarkable. He finished 9th in American League MVP voting, had 16 complete games under his belt, 3 shutouts and a 2.83 ERA. Potter continued to play for the Browns with mixed results until 1948.</p>",
1136				cardinalsPlayer: true,
1137				details: {
1138					position: "P",
1139					bats: "Left",
1140					arm: "Right",
1141					height: {
1142						feet: 5,
1143						inches: 11
1144					},
1145					weight: 180,
1146					city: "Mount Morris, IL",
1147					born: {
1148						year: 1911,
1149						month: 23,
1150						day: 8
1151					}
1152				}
1153			},
1154
1155			{
1156				key: "floyd-baker",
1157				firstName: "Floyd",
1158				lastName: "Baker",
1159				url: "http://www.baseball-reference.com/players/b/bakerfl01.shtml",
1160				bio: "<p>In his second year with the Browns, Floyd Baker played in 44 games. The year was 1944. And it was the only year the Browns clinched the American League pennant. Coincidence? Possibly. But Baker still called that season the &ldquo;highlight of [his] career.&rdquo;</p>",
1161				details: {
1162					position: "3B, 2B, SS",
1163					bats: "Left",
1164					arm: "Right",
1165					height: {
1166						feet: 5,
1167						inches: 9
1168					},
1169					weight: 160,
1170					city: "Luray, VA",
1171					born: {
1172						year: 1916,
1173						month: 10,
1174						day: 10
1175					}
1176				}
1177			},
1178
1179			{
1180				key: "alvis-shirley",
1181				firstName: "Alvis &ldquo;Tex&rdquo;",
1182				lastName: "Shirley",
1183				url: "http://www.baseball-reference.com/players/s/shirlte01.shtml",
1184				bio: "<p>They called him &ldquo;Tex&rdquo; for good reason. He was known to be a little rowdy, on the mound and off, and he never went without a hat. In Game Four of the 1944 World Series, Tex pitched the last two innings without allowing a run.</p>",
1185				details: {
1186					position: "P",
1187					bats: "Switch",
1188					arm: "Right",
1189					height: {
1190						feet: 6,
1191						inches: 1
1192					},
1193					weight: 175,
1194					city: "Birthright, TX",
1195					born: {
1196						year: 1918,
1197						month: 4,
1198						day: 25
1199					}
1200				}
1201			},
1202
1203			{
1204				key: "mike-chartak",
1205				firstName: "Mike",
1206				lastName: "Chartak",
1207				url: "http://www.baseball-reference.com/players/c/chartmi01.shtml",
1208				bio: "<p>It wasn&rsquo;t hard for Mike Chartak to choose between what he was doing (working the line at a war production factory) and what he wanted to do (play professional baseball full time). It was hard, however, for Chartak to hit the ball in the &lsquo;44 World Series. Two at-bats, two strikeouts — the second of which ended the Browns&rsquo; hopes for a Game 7.</p>",
1209				details: {
1210					position: "RF, 1B",
1211					bats: "Left",
1212					arm: "Left",
1213					height: {
1214						feet: 6,
1215						inches: 2
1216					},
1217					weight: 180,
1218					city: "Brooklyn, NY",
1219					born: {
1220						year: 1916,
1221						month: 4,
1222						day: 28
1223					}
1224				}
1225			},
1226
1227			{
1228				key: "steve-sundra",
1229				firstName: "Steve",
1230				lastName: "Sundra",
1231				url: "http://www.baseball-reference.com/players/s/sundrst01.shtml",
1232				bio: "<p>Steve Sundra tasted World Series victory in 1938, as a member of the Yankees club. He brought a whiff of that victory with him when he joined the Browns, bringing home three consecutive winning records (1942&mdash;1944). He went on to serve in the military for a year, then rejoined the team for a short and much less productive stint.</p>",
1233				details: {
1234					position: "P",
1235					bats: "Right",
1236					arm: "Right",
1237					height: {
1238						feet: 6,
1239						inches: 2
1240					},
1241					weight: 190,
1242					city: "Luxor, PA",
1243					born: {
1244						year: 1910,
1245						month: 3,
1246						day: 27
1247					}
1248				}
1249			},
1250
1251			{
1252				key: "mark-christman",
1253				firstName: "Mark",
1254				lastName: "Christman",
1255				url: "http://www.baseball-reference.com/players/c/chrisma01.shtml",
1256				bio: "<p>Born and raised on Browns&rsquo; baseball, Mark Christman got 148 hits in 148 games for the pennant-winning 1944 team. Christman, with a number six on his jersey, played in all six World Series games, but ended up with six strikeouts and just one RB
1256I. Maybe six wasn&rsquo;t really his number.</p>",
1257				details: {
1258					position: "P",
1259					bats: "Right",
1260					arm: "Right",
1261					height: {
1262						feet: 5,
1263						inches: 11
1264					},
1265					weight: 175,
1266					city: "Maplewood, MO",
1267					born: {
1268						year: 1913,
1269						month: 10,
1270						day: 21
1271					}
1272				}
1273			},
1274
1275			{
1276				key: "lefty-west",
1277				firstName: "Lefty",
1278				lastName: "West",
1279				url: "http://www.baseball-reference.com/players/w/westle01.shtml",
1280				bio: "<p>If Lefty West would have picked up a bat before he picked up a ball, he might have gone by Righty — he hit from the right side of the plate but pitched from the left. West spent &lsquo;44 with the Browns as a reliever and transitioned to a starter in 1945 before bowing out of the big leagues in September of that year.</p>",
1281				details: {
1282					position: "P",
1283					bats: "Right",
1284					arm: "Left",
1285					height: {
1286						feet: 6,
1287						inches: 0
1288					},
1289					weight: 165,
1290					city: "Gibsonville, NC",
1291					born: {
1292						year: 1915,
1293						month: 9,
1294						day: 3
1295					}
1296				}
1297			},
1298
1299			{
1300				key: "ellis-clary",
1301				firstName: "Ellis",
1302				lastName: "Clary",
1303				url: "http://www.baseball-reference.com/players/c/claryel01.shtml",
1304				bio: "<p>He might have gone by &ldquo;Cat,&rdquo; but it was said that Ellis Clary could even make dogs laugh. Batting .256 during his Browns career, Clary probably cracked more jokes than bats. He only saw one at-bat in the &lsquo;44 World Series, but between their habits and his humor, he had a good time. &ldquo;They drank anything that would pour. If you went out with them, you wore a football helmet,&rdquo; he said about the 1944 team. According to some accounts, he&rsquo;d also sneak a listen to Chicago Bears games on the radio during the regular season. But lack of time at the plate didn&rsquo;t keep him out of the game. Clary went on to become a coach and well-respected scout for much of the next 50 years.</p>",
1305				details: {
1306					position: "2B, 3B",
1307					bats: "Right",
1308					arm: "Right",
1309					height: {
1310						feet: 5,
1311						inches: 8
1312					},
1313					weight: 160,
1314					city: "Valdosta, GA",
1315					born: {
1316						year: 1916,
1317						month: 9,
1318						day: 11
1319					}
1320				}
1321			},
1322
1323			{
1324				key: "sam-zoldak",
1325				firstName: "Sam",
1326				lastName: "Zoldak",
1327				url: "http://www.baseball-reference.com/players/z/zoldasa01.shtml",
1328				bio: "<p>&ldquo;Sad Sam&rdquo; Zoldak was a rookie reliever for the 1944 Browns club, but the southpaw never pitched in the World Series. However, he still had a lot to smile about. With his sharp location, he went 23-27 and averaged a respectable 3.59 ERA over his 125-game Browns career. In 1948, Zoldak was traded to the Cleveland Indians for Bill Kennedy and $100,000 — but again was left out of the Fall Classic.</p>",
1329				details: {
1330					position: "P",
1331					bats: "Left",
1332					arm: "Left",
1333					height: {
1334						feet: 5,
1335						inches: 11
1336					},
1337					weight: 185,
1338					city: "Brooklyn, NY",
1339					born: {
1340						year: 1918,
1341						month: 12,
1342						day: 8
1343					}
1344				}
1345			},
1346
1347			{
1348				key: "don-gutteridge",
1349				firstName: "Don",
1350				lastName: "Gutteridge",
1351				url: "http://www.baseball-reference.com/players/g/guttedo01.shtml",
1352				bio: "<p>Don Gutteridge started his major league career as a Cardinal in 1936, and joined the team across town 6 seasons later. Gutteridge was was a skillful and speedy fielder — he once turned 5 double-plays in a single game — though he was more known for his Gas House Gang style. According to Gutteridge, he was in good company: He said the Browns were &ldquo;a bunch of raggedy-assed guys, no college education. They just loved to play baseball.&rdquo; (A mostly true observation.)</p><p>Gutteridge was the leadoff batter in the Game One of the 1944 World Series. But before that, he was witness to the final out in the pennant-clinching last game of the season. He was playing second base when Oscar Grimes popped out to George McQuinn, just behind first. &ldquo;It was a foul ball and it went way high and I run over there&hellip; and I hollered, &lsquo;Squeeze it George, squeeze it George, squeeze it!&rsquo; And old George squeezed it and we won the pennant,&rdquo; Gutteridge recalls. &ldquo;It took me about 15 minutes to get back to the dugout,&rdquo; he explains, &ldquo;because the minute that last ball hit into George [McQuinn]&rsquo;s glove, we were swamped. George and I had to fight our way over to our dugout&hellip; There was a lot, a lot of people on that field long before we ever got there. I think (the fans) already jumped over the wall and they swarmed us.&rdquo;</p>",
1353				cardinalsPlayer: true,
1354				details: {
1355					position: "2B, 3B",
1356					bats: "Right",
1357					arm: "Right",
1358					height: {
1359						feet: 5,
1360						inches: 10
1361					},
1362					weight: 165,
1363					city: "Pittsburg, KS",
1364					born: {
1365						year: 1912,
1366						month: 6,
1367						day: 19
1368					}
1369				}
1370			},
1371
1372			{
1373				key: "red-hayworth",
1374				firstName: "Red",
1375				lastName: "Hayworth",
1376				url: "http://www.baseball-reference.com/players/h/haywora01.shtml",
1377				bio: "<p>Red Hayworth&rsquo;s older brother, Ray, was a longtime catcher for the Detroit Tigers, and briefly played for the Brooklyn Dodgers and the New York Giants. In 1942, Ray even caught a game for the St. Louis Browns. Red joined the Browns two years later, after being stuck in the Yankees&rsquo; minor league clubs. Red&rsquo;s first season with the Browns (1944) was the highlight of his 2-year major league career. He was the starting catcher for all 6 games of the Browns&rsquo; only World Series appearance.</p>",
1378				details: {
1379					position: "C",
1380					bats: "Right",
1381					arm: "Right",
1382					height: {
1383						feet: 6,
1384						inches: 1
1385					},
1386					weight: 200,
1387					city: "High Point, NC",
1388					born: {
1389						year: 1916,
1390						month: 5,
1391						day: 14
1392					}
1393				}
1394			},
1395
1396			{
1397				key: "george-mcquinn",
1398				firstName: "George",
1399				lastName: "McQuinn",
1400				url: "http://www.baseball-reference.com/players/m/mcquige02.shtml",
1401				bio: "<p>The only thing that wasn&rsquo;
1401t quiet about George McQuinn was his bat. He consistently led the Browns at the plate, racking up over 1,200 hits in his 8 years with the team. He also caught the final pop fly that clinched the AL pennant for the Browns. (Don Gutteridge tells it vividly.) The star of the &lsquo;44 World Series, he hit .438 and drove in 5 of the team&rsquo;s 9 runs. The six time All-Star also hit the Browns&rsquo; only home run in the series, leading the team to a 2-1 victory in Game One.</p>",
1402				details: {
1403					position: "1B",
1404					bats: "Left",
1405					arm: "Left",
1406					height: {
1407						feet: 5,
1408						inches: 11
1409					},
1410					weight: 165,
1411					city: "Arlington, VA",
1412					born: {
1413						year: 1910,
1414						month: 29,
1415						day: 05
1416					}
1417				}
1418			},
1419
1420			{
1421				key: "frank-mancuso",
1422				firstName: "Frank",
1423				lastName: "Mancuso",
1424				url: "http://www.baseball-reference.com/players/m/mancufr01.shtml",
1425				bio: "<p>In 1943, Frank Mancuso couldn&rsquo;t even walk. As an Army paratrooper, he broke his back and leg in a botched practice jump. Doctors told him he&rsquo;d never play baseball again. They were wrong.</p><p>Because of his injury, he couldn&rsquo;t field fly balls — he&rsquo;d pass out if he looked straight up. But that didn&rsquo;t keep him from a big-time win. Together with fellow first-year catcher Myron &ldquo;Red&rdquo; Hayworth, Mancuso helped the &lsquo;44 Browns capture the American League championship, the first team to ever do so with two rookie catchers.</p>",
1426				details: {
1427					position: "C",
1428					bats: "Right",
1429					arm: "Right",
1430					height: {
1431						feet: 6,
1432						inches: 0
1433					},
1434					weight: 195,
1435					city: "Houston, TX",
1436					born: {
1437						year: 1918,
1438						month: 5,
1439						day: 23
1440					}
1441				}
1442			},
1443
1444			{
1445				key: "milt-byrnes",
1446				firstName: "Milt",
1447				lastName: "Byrnes",
1448				url: "http://www.baseball-reference.com/players/b/byrnemi01.shtml",
1449				bio: "<p>They called him Skippy, but Milt Byrnes sure knew how to draw a walk. In his 3-year major league career, he earned 199 bases on balls — the 26th highest BB count of all batters since 1901 with 1,500 career at-bats.</p>",
1450				details: {
1451					position: "OF",
1452					bats: "Left",
1453					arm: "Left",
1454					height: {
1455						feet: 5,
1456						inches: 10
1457					},
1458					weight: 170,
1459					city: "St. Louis, MO",
1460					born: {
1461						year: 1916,
1462						month: 11,
1463						day: 15
1464					}
1465				}
1466			},
1467
1468			{
1469				key: "joe-schultz",
1470				firstName: "Joe",
1471				lastName: "Schultz",
1472				url: "http://www.baseball-reference.com/players/s/schuljo05.shtml",
1473				bio: "<p>Joe Schultz was practically born at the backstop. His dad, Joe Sr., was an outfielder for all but one of the National League teams. In 1932, Joe Sr. was managing the Class A Houston Buffaloes. Though he was just the batboy, Joe Jr. made his first professional plate appearance as a pinch hitter at the ripe age of 13. Ultimately, Joe Jr. would spend most of his career in his hometown. He was a backup catcher and pinch hitter for the Browns, bringing his solid glove and even better sense of humor to 218 games over 6 years (1943-1948).</p>",
1474				details: {
1475					position: "C, PH",
1476					bats: "Left",
1477					arm: "Right",
1478					height: {
1479						feet: 5,
1480						inches: 11
1481					},
1482					weight: 180,
1483					city: "Chicago, IL",
1484					born: {
1485						year: 1918,
1486						month: 8,
1487						day: 29
1488					}
1489				}
1490			},
1491
1492			{
1493				key: "al-zarilla",
1494				firstName: "Al",
1495				lastName: "Zarilla",
1496				url: "http://www.baseball-reference.com/players/z/zarilal01.shtml",
1497				bio: "<p>&ldquo;Zarilla slud into third!&rdquo; called Dizzy Dean. This now-sorta-famous quip isn&rsquo;t the only reason we remember Al &ldquo;Zeke&rdquo; Zarilla. He scored and drove in a run to help the Browns win Game 3 of the 1944 World Series.</p><p>After the Browns: Zarilla was traded to the Boston Red Sox in 1949, where he would later achieve career highs in slugging percentage, runs and walks. On June 8, 1950, he tied a still-standing major league record when he hit 4 doubles in a game. He also spent time with the White Sox and, returned to the Browns briefly, but he finished out his career with the Red Sox in 1953.</p>",
1498				details: {
1499					position: "OF",
1500					bats: "Left",
1501					arm: "Right",
1502					height: {
1503						feet: 5,
1504						inches: 11
1505					},
1506					weight: 180,
1507					city: "Los Angeles, CA",
1508					born: {
1509						year: 1919,
1510						month: 5,
1511						day: 1
1512					}
1513				}
1514			},
1515
1516			{
1517				key: "chuck-stevens",
1518				firstName: "Chuck",
1519				lastName: "Stevens",
1520				url: "http://www.baseball-reference.com/players/s/stevech01.shtml",
1521				bio: "<p>After a handful of years in the Browns&rsquo; minor league clubs, Chuck Stevens landed a major league gig in 1941. However, he only played 4 games with the Browns before he left for the Air Force. Stevens rejoined the Browns for a season in 1946, and again in 1948.</p><p>On July 9, 1948, Stevens came up to bat against Satchel Paige. It was Paige&r
1521squo;s first game in the Bigs. The two had faced each other in several exhibition games in California, and, although Paige&rsquo;s pitching reputation preceded him, Stevens hadn&rsquo;t thought too much of it. On the second pitch, he smacked a line drive out to left field, marking the first major league hit off of the soon-to-be legend.</p><p>&ldquo;Everybody was taken by Satchel and his reputation was awesome,&rdquo; Stevens said. &ldquo;When I got that hit against him, I was never terribly impressed by it, but the people thought that was a great accomplishment. To me, it was just, he was just another pitcher.&rdquo;</p>",
1522				details: {
1523					position: "1B",
1524					bats: "Switch",
1525					arm: "Left",
1526					height: {
1527						feet: 6,
1528						inches: 1
1529					},
1530					weight: 180,
1531					city: "Van Houten, NM",
1532					born: {
1533						year: 1918,
1534						month: 7,
1535						day: 10
1536					}
1537				}
1538			},
1539
1540			{
1541				key: "tom-jordan",
1542				firstName: "Tom",
1543				lastName: "Jordan",
1544				url: "http://www.baseball-reference.com/players/j/jordato01.shtml",
1545				bio: "<p>Tom Jordan appeared in all of 39 games in the majors, but spent nearly 20 years playing the game he loved. Jordan started his baseball career at age 18 on a Class D team. Over the next six years, he worked his way up through the system. In 1944, he finally got his chance in the big show. His last cup of coffee was his first plate appearance for the Browns in 1948. Jordan returned to the minors and unaffiliated ball in 1949, where he stayed as a player/manager until the age of 37. Not a bad life for a kid from Lawton, Oklahoma.</p>",
1546				details: {
1547					position: "C, PH",
1548					bats: "Right",
1549					arm: "Right",
1550					height: {
1551						feet: 6,
1552						inches: 1
1553					},
1554					weight: 195,
1555					city: "Lawton, OK",
1556					born: {
1557						year: 1919,
1558						month: 9,
1559						day: 5
1560					}
1561				}
1562			},
1563
1564			{
1565				key: "dick-starr",
1566				firstName: "Dick",
1567				lastName: "Starr",
1568				url: "http://www.baseball-reference.com/players/s/starrdi01.shtml",
1569				bio: "<p>After a rough first season with the Browns (1949), Dick Starr was a bright spot for the Browns in 1950. With a 7-5 record, he was the Browns&rsquo; only pitcher with a winning record.  </p>",
1570				details: {
1571					position: "P",
1572					bats: "Right",
1573					arm: "Right",
1574					height: {
1575						feet: 6,
1576						inches: 3
1577					},
1578					weight: 190,
1579					city: "Kittanning, PA",
1580					born: {
1581						year: 1921,
1582						month: 3,
1583						day: 2
1584					}
1585				}
1586			},
1587
1588			{
1589				key: "george-elder",
1590				firstName: "George",
1591				lastName: "Elder",
1592				url: "http://www.baseball-reference.com/players/e/elderge01.shtml",
1593				bio: "<p>George Elder appeared in only 41 games during his major league career, all with the Browns in 1949. In his career, he hit exactly as many times as he struck out — 11 apiece. He is one of only two major league baseball players from Lebanon, KY.</p>",
1594				details: {
1595					position: "PH, PR, LF",
1596					bats: "Left",
1597					arm: "Right",
1598					height: {
1599						feet: 5,
1600						inches: 11
1601					},
1602					weight: 180,
1603					city: "Lebanon, KY",
1604					born: {
1605						year: 1921,
1606						month: 3,
1607						day: 10
1608					}
1609				}
1610			},
1611
1612			{
1613				key: "neil-berry",
1614				firstName: "Neil",
1615				lastName: "Berry",
1616				url: "http://www.baseball-reference.com/players/b/berryne01.shtml",
1617				bio: "<p>Neil Berry was a utility infielder for the Browns for a mere 37 games in 1953. He was released in late August, then picked up by the Chicago White Sox a few days later. Some would consider it irony when he was traded to Baltimore&rsquo;s shiny new team (sort of) for the 1954 season.</p>",
1618				details: {
1619					position: "SS, 2B, 3B",
1620					bats: "Right",
1621					arm: "Right",
1622					height: {
1623						feet: 5,
1624						inches: 10
1625					},
1626					weight: 168,
1627					city: "Kalamazoo, MI",
1628					born: {
1629						year: 1922,
1630						month: 1,
1631						day: 11
1632					}
1633				}
1634			},
1635
1636			{
1637				key: "johnny-hetki",
1638				firstName: "Johnny",
1639				lastName: "Hetki",
1640				url: "http://www.baseball-reference.com/players/h/hetkijo01.shtml",
1641				bio: "<p>Even though Johnny Hetki only pitched in three games for the 1952 Browns, he still managed to net four strikeouts. He took the mound in a Browns uniform for 9.1 innings total, which is technically a complete game. It just didn&rsquo;t happen all at the same time.</p>",
1642				details: {
1643					position: "P",
1644					bats: "Right",
1645					arm: "Right",
1646					height: {
1647						feet: 6,
1648						inches: 1
1649					},
1650					weight: 202,
1651					city: "Leavenworth, KS",
1652					born: {
1653						year: 1922,
1654						month: 5,
1655						day: 12
1656					}
1657				}
1658			},
1659
1660			{
1661				key: "jim-rivera",
1662				firstName: "Jim",
1663				lastName: "Rivera",
1664				url: "http://www.baseball-reference.com/players/r/riverji01.shtml",
1665				bio: "<p>Daredevil. Army Corpsman. Light-heavyweight boxer. Inmate. And finally, major leaguer. Jungle Jim Rivera, as he came to be called, had many identities. Not all of them were friendly, but they earned him a lot of attention.</p><p>In 1951, Rivera was named the Pacific Coast League MVP. The White Sox quickly snapped him up, then the Browns got him in a 3-team, 8-player trade before the start of the 1952 season.</p><p>Browns manager Rogers Hornsby once said that Rivera was &ldquo;the only man I would pay admission to see.&rdquo; He slid head-first before it was in style. He made crowd-pleasing, game-saving catches. He was an all-around clutch player. As one reporter put it, &ldquo;He runs in the outfield like a deer, on the bases like an express train, and he throws like a rifle.&rdquo;</p><p>Unfortunately, Rivera&rsquo;s spunk and style didn&rsquo;t outweigh his early-season slump. He was traded back to the White Sox, and continued to make the news for the next 10 years.</p>",
1666				details: {
1667					position: "OF",
1668					bats: "Left",
1669					arm: "Left",
1670					height: {
1671						feet: 6,
1672						inches: 0
1673					},
1674					weight: 196,
1675					city: "New York, NY",
1676					born: {
1677						year: 1921,
1678						month: 7,
1679						day: 22
1680					}
1681				}
1682			},
1683
1684			{
1685				key: "don-lenhardt",
1686				firstName: "Don",
1687				lastName: "Lenhardt",
1688				url: "http://www.baseball-reference.com/players/l/lenhado01.shtml",
1689				bio: "<p>Don Lenhardt was nicknamed &ldquo;Footsie&rdquo; because he often had trouble finding shoes that fit. He also had trouble finding a club that fit — he was traded 6 times in 5 years. With a career high of 22 home runs, his best season was his first. (This begs the question: which came first, the trades or the stats?) Lenhardt was also one of the players to be transplanted when the Browns became the Baltimore Orioles in 1954.</p>",
1690				details: {
1691					position: "LF, 1B, 3B",
1692					bats: "Right",
1693					arm: "Right",
1694					height: {
1695						feet: 6,
1696						inches: 3
1697					},
1698					weight: 190,
1699					city: "Alton, IL",
1700					born: {
1701						year: 1922,
1702						month: 10,
1703						day: 4
1704					}
1705				}
1706			},
1707
1708			{
1709				key: "tom-wright",
1710				firstName: "Tom",
1711				lastName: "Wright",
1712				url: "http://www.baseball-reference.com/players/w/wrighto01.shtml",
1713				bio: "<p>Tom Wright was known as a pinch hitting specialist. In a 1950 Sporting News article, Steve O&rsquo;Neill said, &ldquo;You can call on him any time and he&rsquo;s just as likely as not to deliver the hit you need. Lots of players lose that split-second timing when they lay off for a while. But Tom can sit on the bench for three weeks, then get up and hit just as well as if he was in there every day.&rdquo; Wright would have much rather played every day than sit on the bench for three weeks, but it&rsquo;s good to know he could have done either equally as well.</p>",
1714				details: {
1715					position: "PH, OF",
1716					bats: "Left",
1717					arm: "Right",
1718					height: {
1719						feet: 5,
1720						inches: 11
1721					},
1722					weight: 180,
1723					city: "Shelby, NC",
1724					born: {
1725						year: 1923,
1726						month: 9,
1727						day: 22
1728					}
1729				}
1730			},
1731
1732			{
1733				key: "billy-demars",
1734				firstName: "Billy",
1735				lastName: "Demars",
1736				url: "http://www.baseball-reference.com/players/d/demarbi01.shtml",
1737				bio: "<p>In his 209 games with the Browns, Billy &ldquo;Kid&rdquo; DeMars only had 13 RBIs. Although he came up short on the field, he went on to become one of the game&rsquo;s most respected batting coaches.</p><p>&ldquo;Baseball was my lifetime, 58 years. Every job has its ups and downs, but I still can't see me doing anything else. It was a great ride.&rdquo; &mdash; Billy DeMars</p><p>After the Browns: Billy DeMars didn&rsquo;t move with the Browns to Baltimore, but in 1958 he began an 11-year post as a manager in the Orioles&rsquo; farm system. From there, he moved up to the majors and found success as a batting coach. He was with the Phillies for 13 years, including their franchise-first World Series win in 1980. He later coached the Expos and the Reds, and earned the high respect of Pete Rose, who said DeMars was the best hitting coach he&rsquo;d ever had.</p>",
1738				details: {
1739					position: "SS, 3B",
1740					bats: "Right",
1741					arm: "Right",
1742					height: {
1743						feet: 5,
1744						inches: 10
1745					},
1746					weight: 160,
1747					city: "Brooklyn, NY",
1748					born: {
1749						year: 1925,
1750						month: 8,
1751						day: 26
1752					}
1753				}
1754			},
1755
1756			{
1757				key: "frank-saucier",
1758				firstName: "Frank",
1759				lastName: "Saucier",
1760				url: "http://www.baseball-reference.com/players/s/saucifr01.shtml",
1761				bio: "<p>Out of the 14 times that Frank Saucier stepped up to the plate for the 1951 Browns, he&rsquo;s usually remembered for the one time he was asked not to. Saucier was replaced by pinch-hitter and shortest-ever baseball player Eddie Gaedel as part of a Bill Veeck promotional stunt in August 1951.</p>",
1762				details: {
1763					position: "PH, PR, OF",
1764					bats: "Left",
1765					arm: "Right",
1766					height: {
1767						feet: 6,
1768						inches: 1
1769					},
1770					weight: 180,
1771					city: "Leslie, MO",
1772					born: {
1773						year: 1926,
1774						month: 5,
1775						day: 28
1776					}
1777				}
1778			},
1779
1780			{
1781				key: "johnny-groth",
1782				firstName: "Johnny",
1783				lastName: "Groth",
1784				url: "http://www.baseball-reference.com/players/g/grothjo01.shtml",
1785				bio: "<p>In 1949, Life magazine dubbed a young Johnny Groth the next Joe DiMaggio. Just 4 years later, Groth had the worst season of his career with the Browns during their final season in St. Louis. Even after a dismal season, he provided a little light at the end of a long tunnel for the soon-to-be defunct team: He scored the last-ever run for the Browns in a 2-1 loss to the Chicago White Sox on September 27, 1953.</p>",
1786				details: {
1787					position: "CF",
1788					bats: "Right",
1789					arm: "Right",
1790					height: {
1791						feet: 6,
1792						inches: 0
1793					},
1794					weight: 182,
1795					city: "Chicago, IL",
1796					born: {
1797						year: 1926,
1798						month: 7,
1799						day: 23
1800					}
1801				}
1802			},
1803
1804			{
1805				key: "ed-mickelson",
1806				firstName: "Ed",
1807				lastName: "Mickelson",
1808				url: "http://www.baseball-reference.com/players/m/mickeed01.shtml",
1809				bio: "<p>Ed Mickelson recorded his first hit with the Browns&rsquo; cross-town rivals in 1950, but his last one was a little more memorable. Mickelson recorded the last-ever RBI for the Browns in a 2-1 extra-innings loss to the Chicago White Sox in September 1953.</p>",
1810				cardinalsPlayer: true,
1811				details: {
1812					position: "1B",
1813					bats: "Right",
1814					arm: "Right",
1815					height: {
1816						feet: 6,
1817						inches: 3
1818					},
1819					weight: 205,
1820					city: "Ottawa, IL",
1821					born: {
1822						year: 1926,
1823						month: 9,
1824						day: 9
1825					}
1826				}
1827			},
1828
1829			{
1830				key: "don-johnson",
1831				firstName: "Don",
1832				lastName: "Johnson",
1833				url: "http://www.baseball-reference.com/players/j/johnsdo03.shtml",
1834				bio: "<p>Although he wasn&rsquo;t exactly a rookie, one could say Don Johnson cut his pitching teeth during his years with the Browns. His two losing seasons (1950-1951) were a poor measure of his future prowess — he went on to become the International League&rsquo;s most valuable pitcher in 1957.</p>",
1835				details: {
1836					position: "P",
1837					bats: "Right",
1838					arm: "Right",
1839					height: {
1840						feet: 6,
1841						inches: 3
1842					},
1843					weight: 200,
1844					city: "Portland, OR",
1845					born: {
1846						year: 1926,
1847						month: 11,
1848						day: 12
1849					}
1850				}
1851			},
1852
1853			{
1854				key: "roy-sievers",
1855				firstName: "Roy",
1856				lastName: "Sievers",
1857				url: "http://www.baseball-reference.com/players/s/sievero01.shtml",
1858				bio: "<p>Roy &ldquo;Squirrel&rdquo;
1858 Sievers had a stellar rookie year. In fact, he was the American League Rookie of the Year in 1949, and was 18th in line for MVP. Sievers certainly earned it — he batted .306 with 16 home runs and 91 RBI. Shoulder and arm injuries crippled his playing time in his last three years with the Browns, but he remained a full-time major league player until the mid-1960s.</p>",
1859				details: {
1860					position: "OF, 1B",
1861					bats: "Right",
1862					arm: "Right",
1863					height: {
1864						feet: 6,
1865						inches: 1
1866					},
1867					weight: 195,
1868					city: "St. Louis, MO",
1869					born: {
1870						year: 1926,
1871						month: 11,
1872						day: 18
1873					}
1874				}
1875			},
1876
1877			{
1878				key: "hal-hudson",
1879				firstName: "Hal",
1880				lastName: "Hudson",
1881				url: "http://www.baseball-reference.com/players/h/hudsoha01.shtml",
1882				bio: "<p>Some called him &ldquo;Bud.&rdquo; Others called him &ldquo;Lefty.&rdquo; After 9 seasons working his way through the Browns&rsquo; minor league clubs, he was finally called up. In 1952, the southpaw pitched relief in 3 games — half of his entire major league career.</p>",
1883				details: {
1884					position: "P",
1885					bats: "Left",
1886					arm: "Left",
1887					height: {
1888						feet: 5,
1889						inches: 10
1890					},
1891					weight: 175,
1892					city: "Grosse Pointe, MI",
1893					born: {
1894						year: 1927,
1895						month: 5,
1896						day: 4
1897					}
1898				}
1899			},
1900
1901			{
1902				key: "al-naples",
1903				firstName: "Al",
1904				lastName: "Naples",
1905				url: "http://www.baseball-reference.com/players/n/napleal01.shtml",
1906				bio: "<p>Al Naples&rsquo; most memorable hit was also his only hit. Ever. It was a double. Way to hustle, Al.</p><p>&ldquo;I ran like all get-out when I poked that double down the right field line for my first hit in the Big Show. I felt rather good after that.&rdquo;  &mdash; Al Naples, in One Hit Wonders: Baseball Stories (George Rose)</p>",
1907				details: {
1908					position: "SS",
1909					bats: "Right",
1910					arm: "Right",
1911					height: {
1912						feet: 5,
1913						inches: 9
1914					},
1915					weight: 168,
1916					city: "Staten Island, NY",
1917					born: {
1918						year: 1926,
1919						month: 8,
1920						day: 29
1921					}
1922				}
1923			},
1924
1925			{
1926				key: "billy-hunter",
1927				firstName: "Billy",
1928				lastName: "Hunter",
1929				url: "http://www.baseball-reference.com/players/h/huntebi03.shtml",
1930				bio: "<p>Billy Hunter&rsquo;s first year with the Browns was the last year the club existed: 1953. Batting just over the Mendoza line, Hunter earned his keep as starting shortstop by flashing his leather — and his team spirit. Perhaps surprisingly, Hunter hit the last home run in Browns history on September 26, 1953. Hunter was one of few Brownies who went on to play for the 1954 Baltimore Orioles club.</p>",
1931				details: {
1932					position: "SS",
1933					bats: "Right",
1934					arm: "Right",
1935					height: {
1936						feet: 6,
1937						inches: 0
1938					},
1939					weight: 180,
1940					city: "Punxatawney, PA",
1941					born: {
1942						year: 1928,
1943						month: 4,
1944						day: 6
1945					}
1946				}
1947			},
1948
1949			{
1950				key: "joe-demaestri",
1951				firstName: "Joe",
1952				lastName: "Demaestri",
1953				url: "http://www.baseball-reference.com/players/d/demaejo01.shtml",
1954				bio: "<p>Joe DeMaestri didn&rsquo;t have much of a bat, but he had a solid glove. And when it came to Rogers Hornsby, he had sharp words and no sugar for coating. &ldquo;He was the worst manager and worst person I ever played for,&rdquo; DeMaestri said. &ldquo;Everyone hated him.&rdquo; The only time he liked Hornsby was when Hornsby got fired. Marty Marion became skipper, and DeMaestri took Marion&rsquo;s spot at short. Also short was DeMaestri&rsquo;s time on the Browns. He was traded to the White Sox after just 81 games with the team.</p>",
1955				details: {
1956					position: "SS",
1957					bats: "Right",
1958					arm: "Right",
1959					height: {
1960						feet: 6,
1961						inches: 0
1962					},
1963					weight: 170,
1964					city: "San Francisco, CA",
1965					born: {
1966						year: 1928,
1967						month: 12,
1968						day: 9
1969					}
1970				}
1971			},
1972
1973			{
1974				key: "bud-thomas",
1975				firstName: "Bud",
1976				lastName: "Thomas",
1977				url: "http://www.baseball-reference.com/players/t/thomabu02.shtml",
1978				bio: "<p>Bud Thomas played all 14 games of his career in September 1951. During those 14 games, he had 20 at-bats, 7 hits, 2 stolen bases and 1 home run. Not too shabby, Bud.</p>",
1979				details: {
1980					position: "SS",
1981					bats: "Right",
1982					arm: "Right",
1983					height: {
1984						feet: 6,
1985						inches: 0
1986					},
1987					weight: 180,
1988					city: "Sedalia, MO",
1989					born: {
1990						year: 1929,
1991						month: 3,
1992						day: 10
1993					}
1994				}
1995			},
1996
1997			{
1998				key: "don-larsen",
1999				firstName: "Don",
2000				lastName: "Larsen",
2001				url: "http://www.baseball-reference.com/players/l/larsedo01.shtml",
2002				bio: "<p>His rookie (and only) season with the Browns, Don Larsen finished with a 7-12 record. But he was first on the team in innings pitched (192⅔) and complete games (7), and second in strikeouts. He also held the then-record for consecutive hits by a pitcher, with 7. Yet, his greatest victory didn&rsquo;t come until 1956, when he pitched the only perfect game in World Series history&hellip; for the Yankees.</p><p>After the Browns: Larsen stayed on in Baltimore when the Browns became the Orioles in 1954. That year, he led the league in losses, but one of his three wins included a 10-0 shutout against the Yankees. In 1956, his luck had turned around. He pitched a 4-hit shutout in a regular season doubleheader against the Orioles. Then, he made baseball — and World Series — history. One of only 23 perfect games in MLB history, Larsen&rsquo;s 97-pitch no-no came in Game 5, wearing Yankee pinstripes, facing the Dodgers.</p>",
2003				details: {
2004					position: "P",
2005					bats: "Right",
2006					arm: "Right",
2007					height: {
2008						feet: 6,
2009						inches: 4
2010					},
2011					weight: 215,
2012					city: "Mmichigan City, IN",
2013					born: {
2014						year: 1929,
2015						month: 8,
2016						day: 7
2017					}
2018				}
2019			},
2020
2021			{
2022				key: "jw-porter",
2023				firstName: "J.W.",
2024				lastName: "Porter",
2025				url: "http://www.baseball-reference.com/players/p/porteja01.shtml",
2026				bio: "<p>Browns GM/Owner Bill Veeck wasn&rsquo;t just J.W. Porter&rsquo;s boss when he joined the club in 1952. He was his roommate. Porter, then just 19, lived with Veeck at Sportsman&rsquo;s Park during his 33-game career with the team. Porter might have been better at eating eggs than playing ball. His favorite meal was &ldquo;two dozen over light,&rdquo; which he&rsquo;d eat in one sitting. That&rsquo;s almost 5 times the number of runs he scored during his tenure with the squad.</p>",
2027				cardinalsPlayer: true,
2028				details: {
2029					position: "C, PH, OF",
2030					bats: "Right",
2031					arm: "Right",
2032					height: {
2033						feet: 6,
2034						inches: 2
2035					},
2036					weight: 180,
2037					city: "Shawnee, OK",
2038					born: {
2039						year: 1933,
2040						month: 1,
2041						day: 17
2042					}
2043				}
2044			},
2045			{
2046				key: "babe-martin",
2047				firstName: "Babe",
2048				lastName: "Martin",
2049				url: "http://www.baseball-reference.com/players/m/martiba01.shtml",
2050				bio: "<p>Babe Martin was born Boris Michael Martinovich in Seattle, Washington to Serbian immigrant parents. The Martinovich family moved to Zeigler, Illinois when Babe was year old and subsequently moved to St. Louis, Missouri after the death of Babe’s father.</p><p>He started his professional baseball career in 1940 and had a breakout year in 1944 with the Toledo Mud Hens, batting .350 in 114 games. The following season, he joined the St. Louis Browns. Martin retired in 1954. In 69 Major League games, he had 2 home runs, 18 RBI, and a .214 batting average.</p>",
2051				cardinalsPlayer: false,
2052				details: {
2053					position: "LF, 1B, C",
2054					bats: "Right",
2055					arm: "Right",
2056					height: {
2057						feet: 5,
2058						inches: 11
2059					},
2060					weight: 194,
2061					city: "Seattle, WA",
2062					born: {
2063						year: 1920,
2064						month: 3,
2065						day: 28
2066					}
2067				}
2068		},
2069		{
2070				key: "bill-jennings",
2071				firstName: "Bill",
2072				lastName: "Jennings",
2073				url: "http://www.baseball-reference.com/players/j/jennibi01.shtml",
2074				bio: "<p>A native of St. Louis, Missouri, Jennings played briefly for the St. Louis Browns during the 1951 season. Jennings posted a .179 average (35-for-195) in 64 games for the Browns, driving in 13 runs and scoring 20 times, while collecting 10 doubles, two triples, and one stolen base.</p>",
2075				cardinalsPlayer: false,
2076				details: {
2077					position: "SS",
2078					bats: "Right",
2079					arm: "Right",
2080					height: {
2081						feet: 6,
2082						inches: 2
2083					},
2084					weight: 175,
2085					city: "St. Louis, MO",
2086					born: {
2087						year: 1925,
2088						month: 9,
2089						day: 28
2090					}
2091				}
2092			}
2093		]
2094	},
2095
2096	blog: {
2097
2098		title: "News &amp; Events",
2099
2100		posts: [
2101			{
2102				title: '“The Saint Louis Browns: The Team That Baseball Forgot” Premieres on Nine Network',
2103				slug: "browns-documentary-premiere",
2104				date: "February 20, 2018",
2105				excerpt: "Documentary Preserves a Legacy that was Nearly Erased",
2106				images: {
2107					news: "/images/blog/browns-news-generic1.jpg",
2108					article: "/images/blog/browns-article-generic1.jpg"
2109				},
2110				body: '<p>Continuing our efforts to preserve our beloved team’s legacy, we are excited and proud to announce the premiere of our new documentary “The St. Louis Browns: The Team That Baseball Forgot.” The film will air on Thursday, March 8, 2018 at 8 p.m. CT on KETC-TV, St. Louis’s local PBS affiliate.<p>Thank you to all of the people who contributed time, resources and commentary to this documentary, and a special thanks to our partners at HLK for producing and directing this hour-long film.<p>Narrated by actor and St. Louis native Jon Hamm, the documentary follows the journey from the team’s inception, through their ups and downs, until the sale of the franchise to Baltimore, where they became the Orioles and the history of the Browns was nearly erased. Fans can reminisce at the team’s on-field antics and St. Louis’s original baseball rivalry. Those unfamiliar with the Browns will be introduced to characters like 3-foot-7-inch Eddie Gaedel, a surprise pinch-hitter wearing a batboy uniform with the number 1/8, and will quickly understand the undeniable lovability of this misfit franchise. Audiences everywhere will see that, beneath the tarnish, there is true baseball gold.<p>“The St. Louis Browns: The Team That Baseball Forgot” features archival photos and video footage of the Browns, discussions with St. Louis Browns Historical Society board members Bill Rogers and Emmett McAuliffe, and current interviews with some of the team’s last living players. The film follows the 2017 release of the critically acclaimed book, <i>St. Louis Browns: The Story of a Beloved Team</i>, by Bill Borst, Bill Rogers and Ed Wheatley, and the 2015 launch of our award-winning website.<p>So, tune in and watch as we take a look back and relive the story of what could have been, but never was — of baseball legends lost to time, glorious gimmicks and a beloved team turned fraternity of failure. This is the story of a team that found its place in history by losing its home. But thanks to this documentary, it\'s a story forgotten no more.'
2111			},
2112			{
2113				title: "The St. Louis Browns 2017 Reunion Luncheon",
2114				slug: "browns-2017-reunion-luncheon",
2115				date: "August 30, 2017",
2116				excerpt: "Browns 2017 Reunion Luncheon Set for September 26, 2017",
2117				images: {
2118					news: "/images/blog/browns-news-generic2.jpg",
2119					article: "/images/blog/browns-article-generic2.jpg"
2120				},
2121				body: '<p>Browns 2017 Reunion Luncheon Set for September 26, 2017</p><p>The St. Louis Browns Historical Society and Fan Club announced their 2017 Reunion luncheon set for September 26 featuring Whitey Herzog, Don Larsen and Sonny Siebert. The luncheon will be held at the Holiday Inn Hwy 66 located at 10709 Watson Rd. at Lindbergh, in Sunset Hills – St. Louis, MO at 11:15.</p><p>Reservations for the luncheon can be made on-line from our <a target="_blank"  href="http://thestlbrowns.blogspot.com/2017/08/invitation-to-annual-st-louis-browns.html">reservation blog site</a>. Information is available at 314-892-8632 or e-mail to <a target="_blank"  href="mailto:[email protected]">[email protected]</a>.</p>'
2122			},
2123			{
2124				title: "Introducing a new book: The St. Louis Browns – The Story Of A Beloved Team",
2125				slug: "the-story-of-a-beloved-team",
2126				date: "August 30, 2017",
2127				excerpt: "Introducing a new book: The St. Louis Browns – The Story Of A Beloved Team",
2128				images: {
2129					news: "/images/blog/browns-news-generic1.jpg",
2130					article: "/images/blog/browns-article-generic1.jpg"
2131				},
2132				body: '<p>On September 15, 2017 there will be a national release of St. Louis Browns:  The Story of a Beloved Team, by Bill Borst, Bill Rogers and Ed Wheatley; published by Reedy Press of St. Louis, with a special forward by Bob 
2132Costas.</p><p>Be sure to get in on a first edition of what will certainly become a baseball collector’s item. Our first run is 4000 books and, in addition to being sold through our Fan Club, copies will also be available nationwide in major box stores, as well as online sellers like Amazon and Barnes & Noble, so we’re expecting the first run to go fast. The best way to get your copy is to reserve one when you make your reservations for the St. Louis Browns Fan Club Annual Luncheon, scheduled for Tuesday, September 26, 2017.</p><p>Reservations for the luncheon can be made on-line from our <a target="_blank"  href="http://thestlbrowns.blogspot.com/2017/08/introducing-new-book-st-louis-browns.html">reservation blog site</a>. Information is available at 314-892-8632 or e-mail to <a target="_blank"  href="mailto:[email protected]">[email protected]</a>.</p>'
2133			},
2134			{
2135				title: "Browns 32nd Reunion Luncheon Set for June 9, 2016",
2136				slug: "browns-32nd-reunion-luncheon",
2137				date: "May 5, 2016",
2138				excerpt: "Browns 32nd Reunion Luncheon Set for June 9, 2016",
2139				images: {
2140					news: "/images/blog/browns-news-generic2.jpg",
2141					article: "/images/blog/browns-article-generic2.jpg"
2142				},
2143				body: '<p>Browns 32nd Reunion Luncheon Set for June 9, 2016</p><p>The St. Louis Browns Historical Society and Fan Club announced their 32nd annual luncheon set for June 9 at the Sheraton Westport Chalet Hotel. More than 300 fans are expected with some traveling from coast to coast.</p><p>Club president, Bill Rogers, reports invitations have been sent to family members of the Rogers Hornsby and Satchel Paige families. According to Bill Rogers, these two players rank in the very top of professional baseball history. We may not know if any family members are able to attend , but we’re in close touch with them, says Rogers.</p><p>Reservations for the luncheon can be made on-line from our reservation blog site at <a target="_blank" href="http://2015browns.blogspot.com" >http://2015browns.blogspot.com</a> or by mail. Send check for $48 per reservation to St. Louis Browns Fan Club, PO Box 510047, St. Louis, MO 63161. Information is available at 314-892-8632 or e-mail to <a target="_blank" href="mailto:[email protected]">[email protected]</a>.</p>'
2144			},
2145			{
2146				title: "Yogi, Garver and the 1951 AL MVP Award",
2147				slug: "yogi-garver-and-1951-al-mvp-award",
2148				date: "September 27, 2015",
2149				excerpt: "The passing of Yogi Berra reminds us of a controversey near and dear to the hearts of Browns fans.",
2150				images: {
2151					news: "/images/blog/browns-news-yogi.jpg",
2152					article: "/images/blog/browns-article-yogi.jpg"
2153				},
2154				body: '<p>In 1951, Browns&rsquo; right-handed pitcher Ned Garver was setting the record that still stands for pitchers who won 20 games for a team that finished in last place and lost 100 games.  Better still, Ned was in the fourth year of an incredible four-year rWAR spurt (4.6, 4.1, 7.3, and 5.6) which started right in Garver&rsquo;s rookie season, 1948.  Meanwhile, in &rsquo;51, Yogi could rise no higher than seventh in any major batting category (except for home runs where he was in a three-way tie for fourth place with a not-so-incredible 27 dingers).</p><p>Yogi of course also had &ldquo;being a catcher&rdquo; going for him.  But the Yanks had only the third-best pitching staff in the eight-team league.   And the staff featured - not kids who might need some grooming from their battery-mate - but veteran all-stars like Vic Raschi, Allie Reynolds and Eddie Lopat.  So &ldquo;Where was the beef?&rdquo; (as Yogi might have said himself).</p><p>Fielding-wise, Yogi was solid, but not spectacular, ranking only third in caught-stealing and fielding percentages and ranking first in errors.</p><p>Garver seemed to be the clear MVP.</p><p>And so Ned thought. The night before the announcement was due, back home for the off-season in Ney, Ohio, Ned received a call from a wire service reporter out of Cleveland (Ned doesn&rsquo;t remember whether it was AP or UPI) congratulating Ned on his MVP victory, and asking for his comment.</p><p>But then the announcement came out that Berra had won.</p><div class="image-list"><div class="image"><img src="/images/blog/browns-article-yogi.jpg" alt="Yogi Berra AL M.V.P."><div class="caption">A griming Yogi Berra, center, Squat New York Yankee catcher, receives thumping congratulation from other Major Leaguers at American Baseball Academy in New York on Nov. 7, 1951 after learning that he will be named on November 8, most valuable player in the American League for 1951. Berra polled 184 votes to 157 for runner-up Ned Garver of the St. Louis Browns. From Left to right are: Sid Gordon, Boston Braves; Ed Lopat, Yankees; Berra; Gil Hodges, Brooklyn Dodgers, and Gil McDougald, Yankees. (AP Photo/John Rooney) <em>(John Rooney)</em></div></div></div><p>The theory is that the votes were rigged by the New York press. Both American League and (especially importantly) New York Yankee attendance was falling in 1951, after robust postwar gains for several years. The baseball minions – and the press – decided that the very last thing the game needed was for a member of the laughingstock St. Louis Browns to win the MVP, and a pitcher at that. The likable and comical Yogi was the candidate to bring everybody out of the doldrums.</p><p>Ned himself says that the information he received down through the years was that the New York press even left Garver&rsquo;s name off of some ballots.</p><p>Yogi would repeat the MVP award in 1954 and 1955 with somewhat more formidable numbers.  But his 1951 award was the most inauspicious AL MVP winner until 1965&rsquo;s Zoilo Versailles of the Minnesota Twins.  The Browns, for their part, would never win a modern (post-1931) MVP award.</p><div class="image-list"><div class="image"><img src="/images/blog/ned-garver-browns_6.jpg" alt="Ned Garver"><div class="caption large">&ldquo;Gee, Yogi, gimme a break!&rdquo;</div></div></div>'
2155			},
2156			{
2157				title: "Last of the Living Former Browns",
2158				slug: "last-of-living-former-browns",
2159				date: "August 20, 2015",
2160				excerpt: "In 1902, the original Milwaukee Brewers moved to St. Louis and became the St. Louis Browns.",
2161				images: {
2162					news: "/images/blog/browns-news-generic1.jpg",
2163					article: "/images/blog/browns-article-generic1.jpg"
2164				},
2165				body: '<p>From 1902 through 1953, the St. Louis Browns, won only a single American League pennant and that was in the 1944 WWII year in which much of their Brownie good fortunes were attributable to the fact the Yankees and several other clubs were missing key players to military service while the St. Louis entry fared well with older players and draft-deferred flat foots. The Browns lost to their St. Louis NL rivals, the Cardinals, in six games in the 1944 World Series.</p><p>Over the years, the Browns were known best for finishing last or next to last; the great Hall of Fame first baseman George Sisler, who also led the city&rsquo;s greatest AL club, the 1922 Browns, to a one-game finish behind the Yankees; the single pennant of 1944; Willard Brown hits the first American League HR by a black player for the 1947 Browns; the Barnum &amp; Bailey world of new-in-1951 owner Bill Veeck; the August 19, 1951 appearance of 3&rsquo;7″ Eddie Gaedel as a pinch hitter; Satchel Paige; Fan Manager Night, also in 1951 under Veeck; and Ned Garver winning 20 games for a last place Browns club that won only 52 games the entire season.</p><p>The Garver feat led to one of the most memorable anecdotes in baseball history. When Garver asked for a raise in 1952, owner Veeck is said to have turned him down with a very simple explanation: &ldquo;No way. We could have finished last without you.&rdquo;</p><p>After a couple of years of falling attendance, more losing baseball, chicanery with also suffering Cardinals, and political pressure from the AL owners who wanted to get rid of Bill Veeck, the Browns were sold to Baltimore interests after the 1953 season. They were re-christened as the Baltimore Orioles in 1954.</p><p>The St. Louis Browns Historical Society and Browns Fan Club has existed since 1984 for the purpose of keeping alive the memory of the St. Louis Browns baseball club. The Pecan Park Eagle wants to thank current president <strong>Bill Rogers</strong> for sending us this new list of the current surviving Browns players. With death of former shortstop Bud Thomas on Saturday, August 15, 2015, the list of living former Browns now has dropped to only twenty names.</p><p><strong>The 20 Surviving St. Louis Browns Players </strong><strong>Through 8/16/2015<br>
2165From Oldest to Youngest by Name, Birthdate, and Age in 2015</strong></p><ol><li>Chuck Stevens 07/10/18 – 97</li><li>Tom Jordan 09/05/19 – 94</li><li>Dick Starr 03/02/21 – 94</li><li>George Elder 03/10/21 – 94</li><li>Neil Berry 01/11/22 – 92</li><li>Johnny Hetki 05/12/22 – 93</li><li>Jim Rivera 07/22/22 – 93</li><li>Tom Wright 09/22/23 – 92</li><li>Billy DeMars 08/26/25 – 90</li><li>Ned Garver 12/25/25 – 90</li><li>Frank Saucier 05/28/26 – 89</li><li>Johnny Groth 07/23/26 – 89</li><li>Ed Mickelson 09/09/26 – 89</li><li>Roy Sievers 11/18/26 – 89</li><li>Hal Hudson 05/04/27 – 88</li><li>Al Naples 08/29/27 – 88</li><li>Billy Hunter 06/04/28 – 87</li><li>Joe DeMaestri 12/09/28 – 87</li><li>Don Larsen 08/07/29 – 86</li><li>J.W. Porter 01/17/33 – 82</li></ol>'
2166			},
2167			{
2168				title: "Celebrating 64th Anniversary of the Smallest Professional (?) Baseball Player Ever",
2169				slug: "celebrating-64th-anniversary-of",
2170				date: "August 20, 2015",
2171				excerpt: "It was August 19, 1951 when Eddie Gaedel stepped up to the plate as a pinch hitter for Frank Saucier. Today we have Eddie Gaedel Societies popping up around the country recognizing short people.",
2172				images: {
2173					news: "/images/blog/browns-news-keefe.jpg",
2174					article: "/images/blog/browns-article-keefe.jpg"
2175				},
2176				body: '<p>Pictured here is Bill Rogers, President of the St. Louis Browns Historical Society and Emmett McAuliffe, VP of the Organization. While not short in physical size, they say they are short of money.  Who isn&rsquo;t?</p><div class="image-list"><div class="image"><img src="/images/blog/rogers-mcauliffe.jpg" alt="Bill Rogers and Emmett McAuliffe"></div></div><p>Pictured in the outset at top left is Tom Keefe, founder of the Eddie Gaedel Society, preaching the gospel about Eddie Gaedel.</p><p>There is one surviving member of this 1951 event, Frank Saucier. Frank is pictured on the Browns luncheon flyer and can be seen at: <a href="http://2015browns.blogspot.com" target="_blank">http://2015browns.blogspot.com</a>.</p>'
2177			},
2178			{
2179				title: "Browns Lose Another Member of History",
2180				slug: "browns-lose-another-member-of-history",
2181				date: "August 19, 2015",
2182				excerpt: "Bud Thomas, 86, passed away on August 15, 2015 in Sedalia, MO. Bud had a short-lived career for the Browns playing in just one season in 1951.",
2183				images: {
2184					news: "/images/blog/browns-news-bud-thomas.jpg",
2185					article: "/images/blog/browns-article-bud-thomas.jpg"
2186				},
2187				body: '<p>Although his time was brief, Bud hit .350 in 20 at bats for the &rsquo;51 team.</p><p>Bud was born in Sedalia in 1929 and was selected by the Browns in the amateur draft in 1947 after then owner Bill Veeck saw him perform at Yankee Stadium under the tutelage of Ty Cobb and Babe Ruth. Although he had an abbreviated career in baseball, he touched many lives during his career as a teacher, principal and school administrator. Give your thoughts and prayers to the Thomas family.</p>'
2188			},
2189			{
2190				title: "Rugger Ardizoia, 95, Made Lone Big League Appearance at Sportsman's Park in '47",
2191				slug: "rugger-ardizoia-95-made-lone-appearance",
2192				date: "July 21, 2015",
2193				excerpt: "Pitcher Mopped Up 15-5 Loss to Muddy Ruel's Browns*",
2194				images: {
2195					news: "/images/blog/browns-news-ardizoia.jpg",
2196					article: "/images/blog/browns-article-ardizoia.jpg"
2197				},
2198				body: '<p>Gave Up 2-Run Homer to Fellow San Franciscan and Iwo Jima &lsquo;Teammate&rsquo; Wally Judnich.</p><p>Yankee Was One of Only 7 Players in Major League History Born in Italy.</p><p><em>* There are no surviving members of the 1947 Browns. The last survivor, John Lester &ldquo;Les&rdquo; Moss, died August 29, 2012.</em></p>'
2199			},
2200			{
2201				title: 'Cubs Manager Maddon: "Browns were more popular than Cardinals"',
2202				slug: "cubs-manager-maddon-browns-were-more",
2203				date: "June 28, 2015",
2204				excerpt: "Chicago Cubs manager Joe Maddon was discussing with MLB Network the tenacity of Central-division rivals the St. Louis Cardinals and felt the need to name-check the Browns.",
2205				images: {
2206					news: "/images/blog/browns-news-maddon.jpg",
2207					article: "/images/blog/browns-article-maddon.jpg"
2208				},
2209				body: '<p>Keep the name alive Joe! I wonder if he would want to take our fan club membership <a href="/#/membership">pledge</a>?</p><p>Read Joe&rsquo;s Browns comment at: <a href="http://m.mlb.com/news/article/122414962/mike-bauman-no-adam-wainwright-no-problem-for-determined-cardinals" target="_blank">http://m.mlb.com/news/article/122414962/mike-bauman-no-adam-wainwright-no-problem-for-determined-cardinals</a></p>'
2210			},
2211			{
2212				title: "Present-day Cardinals Slugger Has Browns Family Roots",
2213				slug: "present-day-cardinals-slugger-has",
2214				date: "June 28, 2015",
2215				excerpt: "When recent AAA call-up Greg Garcia hit his first major-league homerun Friday night, a pinch-hit job, most fans probably did not realize that Garcia comes from a fam
2215ily with deep baseball roots",
2216				images: {
2217					news: "/images/blog/browns-news-garcia.jpg",
2218					article: "/images/blog/browns-article-garcia.jpg"
2219				},
2220				body: '<p>... that all started with the St. Louis Browns in 1937.  The 24-year old infielder&rsquo;s 94-year old grandfather, <strong>Dave Garcia Sr.</strong>,  was an infielder signed by the St. Louis Browns as a 16-year-old in 1937.</p><p>The elder Garcia, well and active at age 94 living in San Diego, spent a lifetime in baseball as a manager, coach and scout. He has watched every living Hall of Famer from the dugout or the field. He was a minor league teammate of Ty Cobb Jr. <a href="http://www.nytimes.com/2009/05/03/sports/baseball/03garcia.html" target="_blank">A semi-recent New York Times article on Dave.</a></p><div class="image-list"><div class="image"><img src="/images/blog/browns-article-garcia.jpg" alt="Dave Garcia Sr."></div><div class="image"><img src="/images/blog/059f40ab_mlbam.jpg" alt="Greg Garcia" width="212" height="320"></div></div>'
2221			},
2222			{
2223				title: "When the Browns Weren't the Browns: Alternate Nicknames, 1902-1953",
2224				slug: "when-browns-werent-browns-alternate",
2225				date: "June 28, 2015",
2226				excerpt: "If you go back into the early days of baseball, team nicknames were more informal than they are today. Indeed many fans took to calling their team what their favorite newspaper called them.",
2227				images: {
2228					news: "/images/blog/browns-news-raven.jpg",
2229					article: "/images/blog/browns-article-raven.jpg"
2230				},
2231				body: '<p>Although &ldquo;the Browns&rdquo; was the official nickname of the franchise beginning in 1902, a few other names popped up, even one that appeared to be official.</p><p>According to <em>Baseball Team Names: A Worldwide Dictionary, 1869-2011</em>, &ldquo;In the era 1890-1910, some teams received bird nicknames based on their stocking color, i.e. Blackbirds, Bluebirds, Blue Jays, Cardinals, Crows, Doves, Ravens and Redbirds.&rdquo; In 1905 and 1906, according to this book, the Browns were actually officially called <em>the Ravens</em>.</p><p>Through 1909 some newspapers took to referring to the team as the <em>Macaleerites, </em>after the team&rsquo;s inaugural manager, Jimmy McAleer.</p><p>In 1928 the Sporting News Guide referred to the Browns as <em>Howley&rsquo;s Sensations</em>. Dan Howley was the manager of the 1928 team and indeed he seemed to have started the Browns on something of an uptick after the short and futile managerial reign of player-manager George Sisler.</p><p>In 1939, the year the Browns set a franchise record for lowest winning percentage which still stands, they were apparently referred to as the <em>Little Brownies</em>.</p><p>In 1944 the Browns only pennant spurred an explosion of journalistic creativity: <em>Cinderella Boys, Cinderella Brownies, Rags-to-Riches Boys, Sackcloth Brownies, </em>and <em>Sewell&rsquo;s Wonders. </em>And add to the list<em>Sewellmen</em> which I personally have seen in the 1944 <em>Sporting News</em>.</p><p> All in all, the &ldquo;St. Louis Americans&rdquo; suffered through much less nickname identity crisis than did other franchises of the time (see Brooklyn, Cleveland, Boston N.L., Philadelphia N.L. e.g.).</p>'
2232			},
2233			{
2234				title: "Francona Missed High School Graduation to Report to Browns",
2235				slug: "francona-missed-high-school-graduation",
2236				date: "June 13, 2015",
2237				excerpt: "John Patsy &ldquo;Tito&rdquo; Francona was inducted this week in the Western Pennsylvania Interscholastic Athletic League Hall of Fame.",
2238				images: {
2239					news: "/images/blog/browns-news-tito-francona.jpg",
2240					article: "/images/blog/browns-article-tito-francona.jpg"
2241				},
2242				body: '<p>At that banquet, Tito told a story about the circumstances of his being signed by the St. Louis Browns in 1952.  It seems he signed with the Browns the very day before he graduated high school.  And baseball - and the Browns&rsquo; management - proved to be a harsh mistress.</p><p><em>He was ordered to skip graduation ceremonies and report directly to the Browns&rsquo; Class B farm team!</em></p><p>The decision to forgo cap-and-gown and don pinstripes was a good one for Tito.  He went on to have a successful major-league career as a first baseman-outfielder including being elected by Cleveland baseball writers as the 1959 Man of the Year, and an appearance in the second 1961 All-Star game.</p><p>Tito played two years in the Browns farm system before the team was sold to Baltimore: one year with the <strong>York White Roses</strong> and one year with the <strong>Aberdeen Pheasants</strong>.   At Aberdeen, Tito met his future wife, a local girl named Roberta Jackson.  <strong>Terry Francona</strong>, their son and current manager of the Cleveland Indians, was born in Aberdeen in 1959.</p><p>Here is a scorecard featuring Tito as an Aberdeen Pheasant. Note that <strong>Roger Maris</strong> (misspelled Maras), is in the lineup that day as a right-fielder for the <strong>Fargo-Moorhead Twins</strong>.</p><div class="image-list"><div class="image"><img src="/images/blog/aberdeen-pheasants.jpg" alt=""></div><div class="image"><img src="/images/blog/aberdeen-pheasants-2.png" alt=""></div></div><p>The Western Pennsylvania Interscholastic Athletic League was founded in 1907 for high school sports. Its Hall Of Fame includes <strong>Stan Musial</strong> and<strong>Arnold Palmer</strong>.</p><p>Other famous Aberdeen Pheasants that later came up to be major leaguers include <strong>Don Larsen, Bob Turley, Don Lenhardt, Perry Currin</strong> (all very recent attendees at the annual St. Louis Browns Fan Club and Historical Society banquet) and <strong>Blackie Schwamb</strong>.</p><p>Although Tito did not make it up to the big leagues in time to be a Brownie, he did eventually make it to Sportsman&rsquo;s Park as a St. Louis Cardinal.  Tito also played with Baltimore, Cleveland, Chicago (AL), Detroit, Atlanta, Philadelphia, Oakland and Milwaukee.</p><h3>Tito Trivia</h3><ul class="bulleted"><li>was traded twice for the same player: Larry Doby.  Once by the Orioles, and once by the Tigers.</li><li>shares the record (with Paul Baka) of being the player who played in the most contiguous states.  Francona played for teams in seven contiguous states: MO, IL, WI, MI, OH, PA, MD.</li><li>is the only player signed by the Browns to have played into the 1970s.
2242</li></ul><p>Read more: <a href="http://triblive.com/sports/hssports/otherhighschoolsports/8542448-74/wpial-francona-basketball#ixzz3cyUWtJcO" target="_blank">http://triblive.com/sporas a member of the St. Louis Cardinals ts/hssports/otherhighschoolsports/8542448-74/wpial-francona-basketball#ixzz3cyUWtJcO</a></p>'
2243			},
2244			{
2245				title: "Bitsy parade is big on spunk",
2246				slug: "bitsy-parade-is-big-on-spunk",
2247				date: "June 10, 2015",
2248				excerpt: "Dozens gathered around the Tiny Bar on Locust Street to witness the self-proclaimed &quot;world's tiniest parade&quot; to honor the 90th birthday of former Browns player Eddie Gaedel.",
2249				images: {
2250					news: "/images/blog/browns-news-gaedel.jpg",
2251					article: "/images/blog/browns-article-gaedel.jpg"
2252				},
2253				body: '<p><strong>(The following story appeared on the front page of the June 10, 2015 <i>St. Louis Post-Dispatch</i>. The Browns are finally front-page news, 61 years after their last season).</strong></p><p>by Jack Witthaus of the St. Louis Post-Dispatch staff</p><p><strong>ST. LOUIS </strong> Emmett McAuliffe remembers exchanging baseball cards with an older kid in Creve Coeur in the 1960s and happening upon one from the Browns.</p><p>He couldn&rsquo;t believe it. There was another baseball team in St. Louis besides the Cardinals? Immediately, the team&rsquo;s colors, losing tendencies and elf logo mystified him.</p><p>Now, McAuliffe, [an officer in the St. Louis Browns Fan Club,] collects hats and other gear from the Browns. On Monday, he donned a milky white Browns jersey and a bow tie as he told stories about the team&rsquo;s history.</p><p>McAuliffe was among dozens gathered Monday night around the Tiny Bar on Locust Street to witness the self-proclaimed &quot;world&rsquo;s tiniest parade&quot; to honor the 90th birthday of former Browns player Eddie Gaedel.</p><p>The parade featured a Smart car, a float in a child-size wagon pulled by child, a toy dog, a one-man band and the world&rsquo;s smallest horse, Thumbelina. Led by Mayor Francis Slay, the 1/8th-block-long parade started and ended in minutes. Attendees broke into applause when the parade halted at the entrance of the Tiny Bar.</p><p>Parade organizer Aaron Perlut &mdash; a founding partner of Elasticity, a digital marketing and public relations firm at 1010 Locust Street &mdash; helped open the Tiny Bar on May 27. Perlut said the 250-square-foot establishment is used to celebrate the &quot;little guy&quot; in a world that often cherishes huge things.</p><p>At 3 feet, 7 inches, Gaedel was the shortest Major League Baseball player ever to record an at-bat. During his August 1951 debut, Gaedel walked on four straight pitches. Then-Browns owner Bill Veeck signed Gaedel as a part of a stunt. Gaedel died in 1961 at the age of 36.</p><p>A large Gaedel mural greets guests who enter the Tiny Bar, and his name is part of the bar&rsquo;s Wi-Fi password. &quot;He&rsquo;s the patron saint,&quot; Perlut said.</p><p>Although the city issued a permit for Monday&rsquo;s little celebration, Cindy Riordan, executive assistant to the director of streets, said the streets department didn&rsquo;t call the &quot;tiny parade&quot; a parade for permit purposes. Due to the small size, the parade was dubbed a &quot;special event.&quot; Riordan said people who apply for parade permits generally do not ask to hold parades less than a block long.</p><p>&quot;It&rsquo;s definitely the smallest one anyone&rsquo;s called a parade,&quot; she said, noting that it might have been the shortest one in St. Louis history.</p><p>Travis Sheridan operated the 2010 yellow Smart car that was in the parade. He said he liked the atmosphere of the event. Music played while attendees milled around and ate birthday cake.</p><p>Sheridan said St. Louis might have an inferiority complex, but it shouldn&rsquo;t see itself as little. Small events like Monday&rsquo;s parade make Sheridan, a friend of Perlut&rsquo;s, optimistic about the future of the city that he moved to about three years ago.</p><p>&quot;People doing tiny things can have a big impact for St. Louis,&quot; Sheridan said.</p>'
2254			},
2255			{
2256				title: "Marlin's Dee Gordon Chasing Feat Done Only by Cobb, Wagner and Browns' George Sisler.",
2257				slug: "marlins-dee-gordon-chasing-feat-done",
2258				date: "May 30, 2015",
2259				excerpt: "The Miami Marlins' Dee Gordon is chasing this year a feat that has only been accomplished by the Uber-Hall of Famers Ty Cobb, Honus Wagner and Brownie George Sisler.",
2260				images: {
2261					news: "/images/blog/browns-news-george-sisler.jpg",
2262					article: "/images/blog/browns-article-george-sisler.jpg"
2263				},
2264				body: '<p>That feat is leading the major leagues in both batting average and stolen bases.</p><div class="image-list"><div class="image"><img src="/images/blog/dee-gordon.png" alt="Dee Gordon"></div></div><div class="image-list"><div class="image"><img src="/images/blog/browns-article-george-sisler.jpg" alt="George Sisler"><div class="caption medium">George Sisler</div></div><div class="image"><img src="/images/blog/honus-wagner.jpg" alt="Honus Wagner"><div class="caption medium">Honus Wagner</div></div><div class="image"><img src="/images/blog/ty-cobb.jpg" alt="Ty Cobb"><div class="caption medium">Ty Cobb</div></div></div><p>
2264Good luck to Dee! <a href="http://www.nytimes.com/2015/05/31/sports/baseball/marlins-gordon-tries-to-match-notable-names-cobb-sisler-snuffy-stirnweiss.html?_r=0" target="_blank">http://www.nytimes.com/2015/05/31/sports/baseball/marlins-gordon-tries-to-match-notable-names-cobb-sisler-snuffy-stirnweiss.html?_r=0</a></p>'
2265			},
2266			{
2267				title: "75 Years-Ago: First Pro Baseball Game Under the Lights in St. Louis",
2268				slug: "75-years-ago-first-pro-baseball-game",
2269				date: "May 24, 2015",
2270				excerpt: "Browns vs. Indians (and Bob Feller),  Attendance. 24,827",
2271				images: {
2272					news: "/images/blog/browns-news-night-baseball.jpg",
2273					article: "/images/blog/browns-article-night-baseball.jpg"
2274				},
2275				body: '<p>Since the Browns owned the stadium, they got the honors of hosting the first night game. (The Cardinals first was on June 4, and drew only 23,500.)</p><p><a href="http://www.baseball-reference.com/boxes/SLA/SLA194005240.shtml" target="_blank">http://www.baseball-reference.com/boxes/SLA/SLA194005240.shtml</a></p><div class="image-list"><div class="image"><img src="/images/blog/browns-article-night-baseball.jpg" alt=""></div></div>'
2276			},
2277			{
2278				title: "Lookee down by the train depot! I do declare, the St. Louis Browns are passing through our lil' ol' town!",
2279				slug: "lookee-down-by-train-depot-st-louis",
2280				date: "May 7, 2015",
2281				excerpt: "100 years ago this week, the <em>Daily Journal-Gazette</em> of Mattoon, Ill., reported in their April 30 edition:",
2282				images: {
2283					news: "/images/blog/browns-news-branch-rickey.jpg",
2284					article: "/images/blog/browns-article-branch-rickey.jpg"
2285				},
2286				body: '<p>MATTOON &mdash; The St. Louis Browns baseball club of the American League will pass through Mattoon on the Big Four Railroad the morning of May 2.</p><p>I shall leave it to our readers in the railroad buff community to explain the details of the Big Four Railroad (the name popularly given to the Central Pacific Railroad, a/k/a the first transcontinental railroad).*</p><p>The Browns were finishing up a road trip in Cleveland and heading home to St. Louis to begin a homestand Tuesday. <strong>Robert Lee Hedges</strong>, the original owner of the Browns is still owner for one last year. Still on the team is Hall of Famer <strong>Bobby Wallace</strong>, who goes all the way back to the St. Louis Perfectos (they of <a href="http://www.vivaelbirdos.com/2015/5/5/8551277/the-st-louis-perfectos-and-the-birth-of-modern-baseball" target="_blank">&ldquo;best opening record in franchise history fame&rdquo;</a>). <strong>Branch Rickey</strong> is the manager. The Browns are stagnant in 8th place.</p><p>You can peruse other stories noted on April 30, 1915, courtesy of the <em>Mattoon Journal Gazette and Times-Courier</em> <a href="http://jg-tc.com/news/opinion/glancing-back-april--may/article_37f98a07-c319-57fd-bd47-9828b340d1d0.html" target="_blank">website</a>.</p><p>I would note three things:</p><ol class="bulleted"><li>The daily newspaper was the thing, not twitter. But the amount of minutia is roughly the same.</li><li>The Browns are in last place, but simply being part of the &ldquo;Big 8 teams&rdquo; of any one of the three major leagues operating at the time, was, at least by Mattoon standards, an attraction.</li><li>Not sure if there is a freight rail-line still passing through Mattoon, but look at how amazingly straight-arrow it is to pass over there &ldquo;as the crow flies&rdquo; from Cleveland to St. Louis.</li></ol><div class="image-list"><div class="image"><img src="/images/blog/map-stlouis-to-cleveland.png" alt="Google Maps route from St. Louis, MO to Cleveland, OH via airplane"></div></div><p>If you went by Amtrak today, you would have to go through Chicago; if you drove, through Effingham.</p><p><em>* Though I can&rsquo;t resist pointing out that the railroad had its origins with a bill introduced by Senator Thomas Hart Benton of Missouri for a &ldquo;Great National Highway from St. Louis to the Pacific Ocean, straight as may be, with branches to Oregon and Mexico. The Government was to reserve a strip one mile wide for it, so as to provide for every kind of a road and means of conveyance – railway, plank, macadamized, with railroad trains, wagons, stages, pack trains and even sleds in Winter.&rdquo;</em></p>'
2287			},
2288			{
2289				title: "The One-Month Brown",
2290				slug: "the-one-month-brown",
2291				date: "March 25, 2015",
2292				excerpt: "My Way, a new book by Colin Gunderson about Tommy Lasorda, chronicles the life of one of the greatest managers and personalities in baseball history.",
2293				images: {
2294					news: "/images/blog/browns-news-lasorda.jpg",
2295					article: "/images/blog/browns-article-lasorda.jpg"
2296				},
2297				body: '<p>The book leads you on a journey through time as Gunderson takes you from Tommy&rsquo;s upbringing in Norristown, Pennsylvania to his continued service as an admirable baseball ambassador with the Dodgers. However, for a one-month period in 1953, Tommy was destined to be a starting pitcher for the St. Louis Browns.</p><p>Prior to the Browns final season in St. Louis in 1953, Bill Veeck acquired Lasorda for $50,
2297000 from the Brooklyn Dodgers. Convinced that he was going to be able to move the team to Baltimore, Veeck began acquiring talent in anticipation of the move and the $2 million he was promised once he landed in Baltimore. But at this point, Veeck has made too many enemies throughout the league and his continual attempts to move were blocked by other owners determined to force him to sell the team. So, Veeck was obliged to return Lasorda back to the Dodgers during spring training.</p><p>Lasorda would go on to a dubious major league playing career followed by a Hall of Fame managerial career with the Los Angeles Dodgers. Tommy brought championships to Los Angeles in 1981 and 1988 and has served as one of the Dodgers and baseball&rsquo;s greatest champions. However, if not for financial issues and the hatred of Bill Veeck around the league, the man who famously said Dodger blue runs through his veins may, in fact, have bled brown.</p><p>Tommy was gracious enough to be the keynote speaker at the 2010 St. Louis Browns Historical Society luncheon. You can view his speech <a href="https://www.youtube.com/watch?v=GNamjlsXH6U" target="_blank">here</a> and also <a href="http://www.amazon.com/Tommy-Lasorda-Way-Colin-Gunderson/dp/1629370711" target="_blank">buy</a> his new book to learn more about the one-month Brown.</p>'
2298			},
2299			{
2300				title: "St. Louis Browns Historical Society Unveils New Digital Experience",
2301				slug: "new-digital-experience",
2302				date: "March 4, 2015",
2303				excerpt: "Site brings forgotten franchise back to the forefront of baseball history",
2304				images: {
2305					news: "/images/blog/browns-news-generic2.jpg",
2306					article: "/images/blog/browns-article-generic2.jpg"
2307				},
2308				body: '<p>ST. LOUIS &mdash; As the Orioles embark on their 62nd season after abandoning St. Louis, The St. Louis Browns Historical Society, an organization dedicated to preserving the story and legacy of the St. Louis Browns baseball team, today announced the launch of its new website. St. Louis-based digital agency, HLK, developed the new site, <a href="www.thestlbrowns.com" target="_blank">www.thestlbrowns.com</a>.</p><p>&ldquo;What the Browns lacked in the win column, they more than made up for with peculiar happenings and stunts on the diamond, as well as various, records that will never be broken,&rdquo; said Emmett McAuliffe, Historical Society board member.  &ldquo;You could not write a Hollywood script better than what actually happened during the 52 years that this team tried to win games and attract fans on a shoestring budget.&rdquo;</p><p>The Browns Historical Society celebrated the launch of the new site yesterday at Tiny Bar in downtown St. Louis, Mo. A photo from the event can be found at <a href="http://bit.ly/1H7ZkNb" target="_blank">http://bit.ly/1H7ZkNb</a> (from left to right: Joe Leahy, partner, HLK; Emmett McAuliffe, board member, Browns Historical Society; Bill Rogers, president, Browns Historical Society; and Eric Karlovic, partner, HLK).</p><p>Featuring an enhanced experience, the site includes a comprehensive overview of the franchise&rsquo;s storied history, biographies and statistics on St. Louis Browns players, and information about the Society and its members.</p><p>&ldquo;At HLK we believe, it is essential to preserve history through digital channels,&rdquo; noted Eric Karlovic, partner at St. Louis-based digital agency HLK. &ldquo;This site was designed in a meaningful storytelling style and experience that will appeal to existing fans and open an avenue to new audiences so the team and players are never forgotten.&rdquo;</p><p>The site launch is the first tactic of a larger strategy for the Society to preserve and remember the St. Louis Browns history, as well as create interest and increase membership in the Society, including the introduction of new merchandise and a documentary, which are set to launch over the next year.</p><p>The Browns moved to St. Louis in 1902, after playing as the Milwaukee Brewers for only one season, joining the already established Cardinals franchise in a baseball-crazy town. Named the Browns by owners, Robert Lee Hedges and the Orthwein brothers, Ralph and Max, the team reopened Sportsman&rsquo;s Park, which had previously served as home for the American Association St. Louis Browns (who one four-straight pennants).   In the Browns&rsquo; 52 years in St. Louis, the team finished sixth or worse in the American League 33 times and had 41 losing seasons, making the phrase &ldquo;St. Louis. First in shoes, first in booze, and last in the American League&rdquo; popular among the locals.</p><p>Along with a losing record the franchise was often  plagued with poor attendance, with the 1935 
2308season only drawing 80,922 total fans to home games. The Browns had many memorable and notable players, and 13 future Hall of Famers would play for the club at one point in their careers, including George Sisler and Bobby Wallace.</p><p>The franchise played in the World Series only once,  in 1944; however, this success did not come without criticism, as most clubs during the time had lost many of their best players to fight in World War II. The Browns lost the Series to the Cardinals, and within three years, the team was back to last place in the American League.</p><p>Following a string of short-lived owners, the Browns were sold to the colorful Bill Veeck, , who would stop at nothing to attract fans with creative promotions. For his first game as the team&rsquo;s owner, Veeck offered all attendees a free beer or soda. Then, on August 19, 1951, Veeck had 3-foot-7-inch Eddie Gaedel, wearing a batboys&rsquo; uniform, pinch hit. Veeck took a $1,000,000 life insurance policy on Gaedel and threatened his life if he tried to swing at a pitch.</p><p>Although he had some valiant efforts, Veeck was unsuccessful in drawing a crowd and eventually sold the team to a Baltimore attorney at the end of the 1953 season. The club played its last game in St. Louis to a crowd of only 3,174 fans before moving to Baltimore to become the Orioles.</p> <p>&ldquo;It&rsquo;s been over a century since the Browns played their first game in St. Louis, and the Historical Society is dedicated to keeping all of the great, and not so great, moments of the team&rsquo;s history alive,&rdquo; said Bill Rogers, president of the St. Louis Browns Historical Society. &ldquo;We&rsquo;re excited to give fans a new way to learn about and remember the Browns.&rdquo;</p><h3>About the St. Louis Browns Historical Society</h3><p>The St. Louis Browns Historical Society and Fan Club is an organization dedicated to preserving every stat and story of the franchise, so that the history of baseball&rsquo;s most intriguing underdogs can continue to entertain fans. To learn more about the Browns history, players or to become a member of the Society, visit <a target="_blank" href="www.thestlbrowns.com">www.thestlbrowns.com</a>.</p><h3>About HLK</h3><p>HLK is a full-service digital agency driven to create authentic brand experiences. Active clients include Ameren, Nestle Purina, Monsanto, On The Run, Germ-X, St. Louis Cardinals, MapQuest, St. Patrick Center and Webster University.</p>'
2309			},
2310			{
2311				title: "Hank Peters, Baseball Executive, Died January 4, 2015 ",
2312				slug: "hank-peters",
2313				date: "January 5, 2015",
2314				excerpt: "Henry J. &ldquo;Hank&rdquo; Peters began his career after answering an ad from the St. Louis Browns, eventually working his way up to the scouting department.",
2315				images: {
2316					news: "/images/blog/browns-news-hank-peters.jpg",
2317					article: "/images/blog/browns-article-hank-peters.jpg"
2318				},
2319				body: '<p>When the team moved to Baltimore after the 1953 season, Peters declined to make the move and subsequently joined the front office of the <a target="_blank" href="http://en.wikipedia.org/wiki/Oakland_Athletics">Kansas City Athletics</a>.</p><p>During more than a decade with the franchise, Peters would eventually direct the team&rsquo;s scouting and minor league system in the mid-1960s under owner <a target="_blank" href="http://en.wikipedia.org/wiki/Charlie_Finley">Charlie Finley</a>. He held the title of <a target="_blank" href="http://en.wikipedia.org/wiki/General_manager_(baseball)">general manager</a> of the Athletics during the <a target="_blank" href="http://en.wikipedia.org/wiki/1965_Major_League_Baseball_season">1965</a> season.</p><p>Peters joined the <a target="_blank" href="http://en.wikipedia.org/wiki/Cleveland_Indians">Cleveland Indians</a> following the 1965 campaign as director of player personnel and assistant general manager to <a target="_blank" href="http://en.wikipedia.org/wiki/Gabe_Paul">Gabe Paul</a> for the remainder of the 1960s through 1971. He then served as the sixth president in the history of the National Association of Professional Baseball Leagues, the umbrella group that governs <a target="_blank" href="http://en.wikipedia.org/wiki/Minor_league_baseball">minor league baseball</a>, from 1972 to 1975, president and general manager of the Orioles from 1975 to 1987, and president of the Indians from 1987 to 1991.</p><p>As Orioles&rsquo; general manager, he kept the team competitive in the tough American League <a target="_blank" href="http://en.wikipedia.org/wiki/American_League_East_Division">East Division</a>, and won AL pennants in <a target="_blank" href="http://en.wikipedia.org/wiki/1979_Major_League_Baseball_season">1979</a> and <a target="_blank" href="http://en.wikipedia.org/wiki/1983_Major_League_Baseball_season">1983</a>, as well as the <a target="_blank" href="http://en.wikipedia.org/wiki/1983_World_Series">1983</a> World Series.</p><p>Prior to his baseball career, Peters served in the United States Army during World War II. He died of complications from a stroke in <a target="_blank" href="http://en.wikipedia.org/wiki/Boca_Raton,_Florida">Boca Raton, Florida</a> on January 4, 2015, aged 90.</p>'
2320			},
2321			{
2322				title: "He Threw Games for Gamblers Yet He Still Holds Record for Most Innings Pitched Without Allowing a Home Run",
2323				slug: "he-threw-games-for-gamblers",
2324				date: "December 29, 2014",
2325				images: {
2326					news: "/images/blog/browns-news-joe-blong.jpg",
2327					article: "/images/blog/browns-article-joe-blong.jpg"
2328				},
2329				excerpt: "We present now for your amusement, the curious case of one Joe Blong. St. Louis Brown Stockings right-handed pitcher, St. Louis native, son of Irish immigrants, and University of Notre Dame alumnus.",
2330				body: '<p>He holds the major league record for most innings pitched without allowing a home run in a career (320.1 innings). But it also seems he had a nasty habit of throwing games, &ldquo;hippodroming&rdquo;
2330 as the newspapers of the day colorfully called it, and was kicked out of baseball for it not once but twice.</p><p>When Joe and two other Browns teammates were kicked out of baseball and blacklisted from all respectable leagues in November 1877, it was curtains for repeat-offender Blong. How do you develop a reputation for throwing games and still hold a positive record that lasts forever? Perhaps he had so much pitching control that he was able to serve up only singles and doubles so that it did not look too obvious that he was throwing a game? In that case, still remarkable control for a pitcher.</p><p>The modern record is quite a ways off from Blong&rsquo;s mark: (269.1 Greg Minton, San Francisco Giants reliever - June 1, 1979 through May 1, 1982), symptomatic of home runs that happen about 8 times as often as they did in the eighteen seventies. But nonetheless even if someday someone surpasses 320.1 innings, it is not likely to represent the entire career of that pitcher. Organized baseball did not know what a favor they were doing for Joe when they expelled him in 1877: bestowing him with an almost impossible record of pitching an entire career, consisting of more than 300 innings, without giving up a home run.</p><p>Blong is buried in Calvary Cemetery in north St. Louis.</p><p>p.s. for Notre Dame fans, one of Blong&rsquo;s partners in crime was the unfortunately named ballplayer Trick McSorley, his classmate at Notre Dame.</p><p>Here is the account from <a href="http://thisgameofgames.blogspot.com/2007/09/joe-blong.html" target="_blank">This Game of Games</a> blog.</p>'
2331			},
2332			{
2333				title: "St. Louis Browns Were Colorful",
2334				slug: "st-louis-browns-were-colorful",
2335				date: "December 9, 2014",
2336				images: {
2337					news: "/images/blog/browns-news-branch-rickey.jpg",
2338					article: "/images/blog/browns-article-branch-rickey.jpg"
2339				},
2340				excerpt: "Major League Baseball fans in Illinois are divided into several camps. Cardinals fans rule the south, while White Sox fans creep in farther north. The Cubs have a strong base statewide. Sixty years ago, there was another, more interesting choice.",
2341				body: '<p>Until 1953, St. Louis was home to two teams, the National League&lsquo;s Cardinals as well as the Browns of the American League. Though the Browns lost a bundle of games over the decades, they left a legacy of some of baseball&rsquo;s most colorful moments.</p><p>The Browns opened play in St. Louis in 1902, a year after the founding of the American League, when the last-place Milwaukee franchise moved to the Gateway City after only one season. They were named for the color of their uniforms, which were replete with brown trim. The name also had been an early moniker of the other team in town, the Cardinals, before the turn of the century.</p><p>The Browns finished second at 78-58 in that inaugural season, which was not a sign of things to come. In their 52 years in St. Louis, the Browns finished first once, second twice and sixth or worse 33 times. Their ineptitude gave rise to the saying, &ldquo;St. Louis. First in shoes, first in booze and last in the American League.&rdquo;</p><p>Despite their struggles, the Browns never lacked for color. The team gave rise to the brilliant career of Branch Rickey, who came to St. Louis in 1913 from a successful stint as head baseball coach at the </p><p>University of Michigan. Rickey later moved across town and built the first minor-league farm system, which helped the Cardinals win four World Series titles before he left in 1942 for Brooklyn. There, he introduced Jackie Robinson, the first African-American to play in the major leagues.</p><p>&ldquo;The owner of the Browns at the time did not recognize Rickey&rsquo;s value,&rdquo; said Bill Rogers, of St. Louis, who has researched the Browns extensively. &ldquo;Had Rickey stayed on, I think things would have turned out much differently.&rdquo;</p><p>Rickey also is responsible for the player that many believe was the greatest in Browns history. First baseman George Sisler was a former Michigan star who batted .420 with 51 stolen bases and 105 RBIs in 1922 to lead the Browns to a 93-61 record, their best ever. Sisler batted .340 in a 15-year major league career, 12 with the Browns. He was elected to the Baseball Hall of Fame in 1939.</p><p>Poor attendance was a recurring theme in Browns history. The 1935 team drew 80,922 fans for the entire season, and the Great Depression was not entirely to blame. St. Louis never won more than 67 games in a 154-game season at any point in the 1930s and was a miserable 43-111 in 1939.</p><p>Finally, the Browns broke through in 1942, finishing third at 82-69 under manager Luke Sewell.</p><p>With a strong pitching staff and a formidable infield, St. Louis was primed for a run. In 1944, they remained in contention for most of the season and swept a season-ending, four-game series against the Yankees at home to capture the pennant with an 89-65 mark.</p><p>Ironically, their World Series opponents were their crosstown rivals, the Cardinals. Since the early 1920s, the Browns actually had been the Cardinals&rsquo; landlords as the owners of Sportsmans&rsquo; Park. Unfortunately for the Browns, they had to suffer as the Cardinals rose to the top of the National League and routinely outdrew their counterparts at the box office.</p><p>The Browns jumped to a 2-1 Series lead, but the Cardinals won the last three to clinch in six games. &ldquo;The Series appearance was a tremendous shot in the arm for the Browns,&rdquo; said Rogers. &ldquo;But in St. Louis, the fans of one team did not like the other team. Even Stan Musial remarked about that once.&rdquo;</p><p>The Browns nearly repeated in 1945, but were eliminated from the pennant race on the last day of the season. That year, the star attraction for the Browns was Pete Gray, a one-armed outfielder who batted .218 in 77 games in his sole major league season.</p><p>For most of their existence, the Browns were financially strapped, and often had to sell off star players simply to keep afloat. After their glorious run of the mid-1940s, many top players were sold for needed cash, and the team fell into steep decline.</p><p>&ldquo;I hate to say it, but I think the Browns were often mismanaged,&rdquo; remarked Rogers. &ldquo;That put them in a financial bind often, and they had to trade or sell their best players to cover expenses.&rdquo;</p><p>However, there were plenty of memorable episodes. Many were courtesy of the flamboyant Bill Veeck, who bought the team in 1951 from an ownership tandem including Bill DeWitt, whose son is a current Cardinals&rsquo; team owner. Veeck challenged the Cardinals head on with a series of wacky promotions.</p><p>Soon after buying the team, Veeck signed Eddie Gaedel, a three-foot-seven-inch midget to a one-day contract and sent him up to bat in the second game of an Aug. 19, 1951, doubleheader against Detroit. Wearing the number &ldquo;1/8" and creating a strike zone of a mere inch-and-a-half, Gaedel walked on four pitches.</p><p>Six days later, the Browns hosted &ldquo;Grandstand Manager&rsquo;s Night,&rdquo; in which fans were allowed to make on-field decisions. Manager Zack Taylor held up signs such as &ldquo;Should the Browns Bunt?,&rdquo; &ldquo;Take Out the Pitcher?&rdquo; and &ldquo;Steal?,&rdquo; while spectators held signs replying &ldquo;Yes&rdquo; or &ldquo;No.&rdquo; The Browns knocked off the Philadelphia A&rsquo;s 5-3 that night, a highlight for a squad that went 52-102.</p><p>Still, many of the players preferred playing for the Browns than the other team in town. Though the Cardinals never finished lower than second from 1941-49, many Browns were happier with their cellar-dwelling franchise. In an interview for a 2000 book, Don Gutteridge, a former Cardinal who was the Browns&rsquo; second baseman through their 1940s heyday, said that &ldquo;the Cardinals were always pinching pennies. The Browns were a better club to play for than the Cardinals.&rdquo;</p><p>Some of the later Browns are among the franchise&rsquo;s most recognizable names. They include the legendary Satchel Paige, who won 12 games at age 46 in 1952, as well as righthander Ned Garver, who won 20 games in 1951. Garver is one of 23 surviving Browns players today, a list that includes Ottawa native Ed Mickelson, who saw action in seven games for the Browns in 1953 and is said to have driven in the final run in Browns history.</p><p>Mickelson, now 88, played in a total of 18 Major League games over three seasons with the Browns, White Sox and Cardinals and later wrote a memoir of his 11 seasons in pro ball, mostly in the minors.</p><p>Another surviving ex-Brown is Don Larsen, a St. Louis rookie in 1953. Three years later, he tossed a perfect game for New York in the 1956 World Series.</p><p>When the Cardinals were sold to Anheuser-Busch in December 1952, Veeck realized he could no longer survive against a larger-budget rival. His tumultuous run as Browns&rsquo; owner came to an end when he sold the team after the 1953 season. The franchise moved to Baltimore and became the Orioles.</p><p>Sixty years later, the Browns are hardly forgotten. In 1984, the St. Louis Browns Fan Club was founded and now numbers 370 members. The club holds an annual banquet, publishes an in-house magazine and offers a line of collectibles.</p><p>&ldquo;Interest in the Browns is extremely high,&rdquo; said Rogers, the president of the club. &ldquo;Even though only 23 Browns survive, there are tens of thousands of fans left. Even younger people have experienced the Browns through the memories of their parents and grandparents. Like one person said to me, &lsquo;we can&rsquo;t bring back the Browns, but we can at least keep their memory alive.&rsquo; &rdquo;</p>'
2342			}
2343		]
2344	}
2345}
2346
2347module.exports = Data;
2348
2349},{}],3:[function(require,module,exports){
2350
2351var Router = require('./Router');
2352var ViewManager = require('./ViewManager');
2353var ViewMediator = require('./ViewMediator');
2354
2355function Application( descriptor ) {
2356
2357	if( !( this instanceof Application ) )
2358		return new Application( descriptor );
2359
2360	this.settings = descriptor;
2361}
2362
2363Application.prototype = {
2364
2365	init: function() {
2366
2367		var s = this.settings;
2368
2369		if( s === undefined )
2370			throw new Error( 'You must define a settings object at initialization' );
2371
2372		if( s.routes === undefined )
2373			throw new Error( 'You must define routes in your settings object' );
2374
2375		s.autoResize = s.autoResize === undefined ? true : s.autoResize;
2376
2377		this.onRouteCallback = s.onRoute;
2378		s.routes.onRoute = this.show.bind( this );
2379		this.router = Router(s.routes);
2380
2381		this.vm = ViewManager( this.settings );
2382
2383		if( s.autoResize ) {
2384
2385			window.addEventListener( 'resize', this.onResize.bind( this ) );
2386			window.addEventListener( 'orientationchange', this.onResize.bind( this ) );
2387			this.onResize();
2388		}
2389
2390		if( s.initSection ) {
2391			this.show( s.initSection.bind( undefined, this.router.init.bind( this.router ) ) );
2392		} else {
2393			this.router.init();
2394		}
2395	},
2396
2397	show: function( content, data ) {
2398
2399		if( this.onRouteCallback )
2400			this.onRouteCallback( content, data );
2401
2402		if( Array.isArray( content ) ) {
2403
2404			var contents = [];
2405
2406			for( var i = 0, l = content.length; i < l; i ++ ) {
2407
2408				if( typeof content[ i ] == 'object' ) {
2409					contents[ i ] = content[ i ];
2410				} else if( typeof content[ i ] == 'function' ) {
2411					contents[ i ] = new content[ i ];
2412				}
2413			}
2414
2415			this.doShow( ViewMediator.apply( undefined, contents ), data );
2416		} else if( typeof content == 'object' ) {
2417
2418			this.doShow( content, data );
2419		} else if( typeof content == 'function' ) {
2420
2421			this.doShow( new content, data );
2422		}
2423	},
2424
2425	doShow: function( content, data ) {
2426
2427		this.vm.show( content, data );
2428	},
2429
2430	resize: function( w, h ) {
2431
2432		this.vm.resize( w, h );
2433	},
2434
2435	onResize: function( w, h ) {
2436
2437		this.resize( window.innerWidth, window.innerHeight );
2438	},
2439
2440	go: function( to ) {
2441
2442		this.router.go( to );
2443	}
2444}
2445
2446module.exports = Application;
2447},{"./Router":17,"./ViewManager":24,"./ViewMediator":25}],4:[function(require,module,exports){
2448module.exports = ["images/about-photo-bill-borst.png","images/about-photo-bill-rogers.png","images/about-photo-emmett.png","images/about-photo-fred-heger.png","images/about-photo-stl-browns.png","images/about-photo-vicki-martin.png","images/about-stlsports-hof.png","images/arrow-left.png","images/arrow-right.png","images/bg-blog-post-border.jpg","images/bg-border-h.jpg","images/bg-border-v.jpg","images/bg-input.png","images/bg-nav-icon-1-dark.png","images/bg-nav-icon-1.png","images/bg-overlay.png","images/bg-players-controls.png","images/bg-social-email.png","images/bg-social-facebook.png","images/bg-social-twitter.png","images/cards-badge.png","images/hof-badge.png","images/home-text.png","images/icn-facebook-hover.png","images/icn-facebook.png","images/icn-nav-dark.png","images/icn-nav.png","images/icn-twitter-hover.png","images/icn-twitter.png","images/icn-youtube-hover.png","images/icn-youtube.png","images/img-footer-logo.png","images/img-intro-icon.png","images/main-dark.jpg","images/main-light-large.jpg","images/main-light.jpg","images/member-level-bleed-brown.png","images/member-level-gold.png","images/member-level-silver.png","images/type-dark.png","images/type.png"];
2449},{}],5:[function(require,module,exports){
2450
2451var $ = require('./DOM');
2452var Class = require('./oop/Class');
2453var Device = require('./Device');
2454var Util = require('./Utils');
2455var Velocity = require('velocity-animate');
2456
2457var arrowRight, arrowLeft;
2458
2459var Carousel = new Class({
2460
2461	initialize: function( element, opts ) {
2462
2463		this.options = opts;
2464		this.index = 0;
2465		this.el = element;
2466		this.wrapper = $.select('.slides', element);
2467		this.slides = $.select('.slide', element);
2468
2469		this.addListeners();
2470		this.move();
2471	},
2472
2473	addListeners: function() {
2474
2475		var _this = this;
2476		arrowRight = $.select('.arrow-right', this.el)[ 0 ];
2477		arrowLeft = $.select('.arrow-left', this.el)[ 0 ];
2478
2479		if( Device.system.touch ) {
2480
2481			$.on( arrowRight, 'touchend', function() { _this.updateIndex(1) } );
2482			$.on( arrowLeft, 'touchend', function() { _this.updateIndex(-1) } );
2483		} else {
2484
2485			$.on( arrowRight, 'click', function() { _this.updateIndex(1) } );
2486			$.on( arrowLeft, 'click', function() { _this.updateIndex(-1) } );
2487		}
2488	},
2489
2490	move: function() {
2491
2492		var amt = (this.slides[ 0 ].scrollWidth) * (this.index * -1);
2493
2494		Velocity(this.wrapper, {
2495			translateX: amt,
2496			translateZ: 0
2497		}, {
2498			duration: this.options.speed || 350,
2499			easing: this.options.easing || 'easeInOutCubic',
2500			queue: false
2501		});
2502
2503		$.show(arrowLeft);
2504		$.show(arrowRight);
2505
2506		if( this.index == 0 ) $.hide(arrowLeft);
2507		if( this.index == (this.slides.length - 1) ) $.hide(arrowRight);
2508	},
2509
2510	updateIndex: function( amt ) {
2511
2512		this.index = Util.clamp(this.index + amt, 0, this.slides.length - 1);
2513		this.move();
2514	},
2515
2516	resize: function() {
2517
2518		this.move();
2519	}
2520});
2521
2522module.exports = Carousel;
2523},{"./DOM":6,"./Device":7,"./Utils":22,"./oop/Class":28,"velocity-animate":54}],6:[function(require,module,exports){
2524
2525var Class = require('./oop/Class');
2526var qwery = require('qwery');
2527var bonzo = require('bonzo');
2528var on = require('dom-event');
2529var off = on.off;
2530
2531var DOMObj = {
2532
2533	_bonzo: bonzo,
2534
2535	select: function( selector, context ) {
2536
2537		var el = qwery( selector, context );
2538
2539		return el;
2540	},
2541
2542	addChild: function( type, parent ) {
2543
2544		var el = document.createElement(type);
2545
2546		parent.appendChild(el);
2547
2548		return el;
2549	},
2550
2551	append: function( el, parent ) {
2552
2553		bonzo(parent).append(el);
2554	},
2555
2556	prepend: function( el, parent ) {
2557
2558		bonzo(parent).prepend(el);
2559	},
2560
2561	addClass: function( klass, element ) {
2562
2563		if( !element ) {
2564
2565			var html = qwery('html');
2566			bonzo(html).addClass(klass);
2567			
2568		} else {
2569			bonzo( element ).addClass( klass );
2570		}
2571
2572		return this;
2573	},
2574
2575	setClass: function( klass, element ) {
2576
2577		bonzo( element ).attr('class', klass);
2578	},
2579
2580	removeClass: function( element, klass ) {
2581
2582		bonzo(element).removeClass(klass);
2583
2584		return this;
2585	},
2586
2587	attr: function( element, attribute ) {
2588
2589		return bonzo(element).attr(attribute);
2590	},
2591
2592	hasClass: function(element, klass) {
2593
2594		return bonzo(element).hasClass(klass);
2595	},
2596
2597	css: function( element, styles ) {
2598
2599		bonzo( element ).css( styles );
2600
2601		return this;
2602	},
2603
2604	hide: function( element ) {
2605
2606		bonzo( element ).hide();
2607
2608		return this;
2609	},
2610
2611	show: function( element ) {
2612
2613		bonzo( element ).show();
2614
2615		return this;
2616	},
2617
2618	center: function( element, w, h ) {
2619
2620		var height = w || bonzo( element ).dim().height;
2621		var width = h || bonzo( element ).dim().width;
2622
2623		bonzo( element ).css({
2624			position: 'absolute',
2625			top: '50%',
2626			left: '50%',
2627			marginTop: height / -2,
2628			marginLeft: width / -2
2629		});
2630
2631		return this;
2632	},
2633
2634	size: function( element, w, h ) {
2635
2636		var styles = {
2637			width: w,
2638			height: h ? h : w
2639		};
2640
2641		bonzo(element).css(styles);
2642
2643		return this;
2644	},
2645
2646	on: function( el, ev, func ) {
2647
2648		on(el, ev, func);
2649	},
2650
2651	off: function( el, ev, func ) {
2652
2653		off(el, ev, func);
2654	},
2655
2656	html: function( el, html ) {
2657
2658		bonzo(el).html(html);
2659	},
2660
2661	hover: function( el, over, out ) {
2662
2663		this.css(el, { cursor: 'pointer' });
2664
2665		on(el, 'mouseover', over);
2666		on(el, 'mouseout', out);
2667	},
2668
2669	width: function( el, w ) {
2670
2671		if( !w )
2672			return bonzo(el).dim().width
2673		else
2674			bonzo(el).css({
2675				width: h
2676			});
2677	},
2678
2679	height: function( el, h ) {
2680
2681		if( !w ) {
2682			
2683			return bonzo(el).dim().height
2684		} else {
2685
2686			bonzo(el).css({
2687				height: h
2688			});
2689		}
2690	},
2691
2692	transform: function( el, values ) {
2693
2694		var t = "";
2695		var force2d = false;
2696
2697		if ( values.x ) t += "translateX(" + values.x + "px) ";
2698		if ( values.y ) t += "translateY(" + values.y + "px) ";
2699		if ( !force2d ) t += "translateZ(0) ";
2700
2701		if ( values.rotX ) t += "rotateX(" + values.rotX + "deg)  ";
2702		if ( values.rotY ) t += "rotateY(" + values.rotY + "deg)";
2703		if ( values.rotZ ) t += "rotateZ(" + values.rotZ + "deg) ";
2704		else if (values.rotZ ) t += "rotate(" + values.rotZ + "deg) ";
2705
2706		if ( values.scaleX && values.scaleX != 1 ) t += "scaleX(" + values.scaleX + ") ";
2707		if ( values.scaleY && values.scaleY != 1 ) t += "scaleY(" + values.scaleY + ") ";
2708		if ( values.scaleZ && values.scaleZ != 1 ) t += "scaleZ(" + values.scaleZ + ")";
2709		if ( values.scale && values.scale != 1 ) t += "scale(" + values.scale + ")";
2710
2711		bonzo(el).css({
2712			"transform": t
2713		});
2714
2715		return this;
2716	}
2717
2718};
2719
2720module.exports = DOMObj;
2721},{"./oop/Class":28,"bonzo":41,"dom-event":42,"qwery":47}],7:[function(require,module,exports){
2722String.prototype.strpos = function(e) {
2723	return this.indexOf(e) != -1
2724};
2725
2726var Device = function() {
2727
2728	var b = this;
2729	this.agent = navigator.userAgent.toLowerCase();
2730	function a(f) {
2731		var e = document.createElement("div"), d = "Khtml ms O Moz Webkit".split(" "), c = d.length;
2732		if (f in e.style) {
2733			return true
2734		}
2735		f = f.replace(/^[a-z]/, function(g) {
2736			return g.toUpperCase()
2737		});
2738		while (c--) {
2739			if (d[c] + f in e.style) {
2740				return true
2741			}
2742		}
2743		return false
2744	}
2745	this.detect = function(d) {
2746		if (typeof d === "string") {
2747			d = [d]
2748		}
2749		for (var c = 0; c < d.length; c++) {
2750			if (this.agent.strpos(d[c])) {
2751				return true
2752			}
2753		}
2754		return false
2755	};
2756	this.mobile = (!!("ontouchstart" in window) && this.detect(["ios", "iphone", "ipad", "windows phone", "android", "blackberry"])) ? {} : false;
2757	if (this.mobile) {
2758		this.mobile.tablet = window.innerWidth > 1000 || window.innerHeight > 900;
2759		this.mobile.phone = !this.mobile.tablet
2760	}
2761	this.browser = new Object();
2762	this.browser.chrome = this.detect("chrome");
2763	this.browser.safari = !this.browser.chrome && this.detect("safari");
2764	this.browser.firefox = this.detect("firefox");
2765	this.browser.ie = (function() {
2766		if (b.detect("msie")) {
2767			return true
2768		}
2769		if (b.detect("trident") && b.detect("rv:")) {
2770			return true
2771		}
2772	})();
2773	this.browser.version = (function() {
2774		try {
2775			if (b.browser.chrome) {
2776				return Number(b.agent.split("chrome/")[1].split(".")[0])
2777			}
2778			if (b.browser.firefox) {
2779				return Number(b.agent.split("firefox/")[1].split(".")[0])
2780			}
2781			if (b.browser.safari) {
2782				return Number(b.agent.split("version/")[1].split(".")[0].charAt(0))
2783			}
2784			if (b.browser.ie) {
2785				if (b.detect("msie")) {
2786					return Number(b.agent.split("msie ")[1].split(".")[0])
2787				}
2788				return Number(b.agent.split("rv:")[1].split(".")[0])
2789			}
2790		} catch (c) {
2791			return -1
2792		}
2793	})();
2794	this.vendor = (function() {
2795		if (b.browser.firefox) {
2796			return "moz"
2797		}
2798		if (b.browser.opera) {
2799			return "o"
2800		}
2801		if (b.browser.ie && b.browser.version >= 11) {
2802			return ""
2803		}
2804		if (b.browser.ie) {
2805			return "ms"
2806		}
2807		return "webkit"
2808	})();
2809	this.system = new Object();
2810	this.system.retina = window.devicePixelRatio > 1 ? true : false;
2811	this.system.webworker = typeof window.Worker !== "undefined";
2812	this.system.offline = typeof window.applicationCache !== "undefined";
2813	this.system.touch = 'ontouchstart' in document;
2814	this.system.geolocation = typeof navigator.geolocation !== "undefined";
2815	this.system.pushstate = typeof window.history.pushState !== "undefined";
2816	this.system.webcam = !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
2817	this.system.language = window.navigator.userLanguage || window.navigator.language;
2818	this.system.webaudio = typeof window.webkitAudioContext !== "undefined" || typeof window.AudioContent !== "undefined";
2819	this.system.localStorage = typeof window.localStorage !== "undefined";
2820	this.system.fullscreen = typeof document[b.vendor + "CancelFullScreen"] !== "undefined";
2821	this.system.os = (function() {
2822		if (b.detect("mac os")) {
2823			return "mac"
2824		} else {
2825			if (b.detect("windows nt 6.3")) {
2826				return "windows8.1"
2827			} else {
2828				if (b.detect("windows nt 6.2")) {
2829					return "windows8"
2830				} else {
2831					if (b.detect("windows nt 6.1")) {
2832						return "windows7"
2833					} else {
2834						if (b.detect("windows nt 6.0")) {
2835							return "windowsvista"
2836						} else {
2837							if (b.detect("windows nt 5.1")) {
2838								return "windowsxp"
2839							} else {
2840								if (b.detect("linux")) {
2841									return "linux"
2842								}
2843							}
2844						}
2845					}
2846				}
2847			}
2848		}
2849		return "undetected"
2850	})();
2851	this.media = new Object();
2852	this.media.audio = (function() {
2853		if (!!document.createElement("audio").canPlayType) {
2854			return b.detect(["firefox", "opera"]) ? "ogg" : "mp3"
2855		} else {
2856			return false
2857		}
2858	})();
2859	this.media.video = (function() {
2860		var c = document.createElement("video");
2861		if (!!c.canPlayType) {
2862			if (Device.mobile) {
2863				return "mp4"
2864			}
2865			if (b.browser.chrome) {
2866				return "webm"
2867			}
2868			if (b.browser.firefox || b.browser.opera) {
2869				if (c.canPlayType('video/webm; codecs="vorbis,vp8"')) {
2870					return "webm"
2871				}
2872				return "ogv"
2873			}
2874			return "mp4"
2875		} else {
2876			return false
2877		}
2878	})();
2879	this.graphics = new Object();
2880	this.graphics.webgl = (function() {
2881		try {
2882			return !!window.WebGLRenderingContext && !!document.createElement("canvas").getContext("experimental-webgl")
2883		} catch (c) {
2884		}
2885	})();
2886	this.graphics.canvas = (function() {
2887		var c = document.createElement("canvas");
2888		return c.getContext ? true : false
2889	})();
2890	this.styles = new Object();
2891	this.styles.filter = a("filter") && !b.browser.firefox;
2892	this.styles.shader = b.browser.chrome;
2893	this.styles.vendor = (function() {
2894		if (b.browser.firefox) {
2895			return "Moz"
2896		}
2897		if (b.browser.opera) {
2898			return "O"
2899		}
2900		if (b.browser.ie && b.browser.version >= 11) {
2901			return ""
2902		}
2903		if (b.browser.ie) {
2904			return "ms"
2905		}
2906		return "Webkit"
2907	})();
2908	this.styles.vendorTransition = this.styles.vendor.length ? this.styles.vendor + "Transition" : "transition";
2909	this.styles.vendorTransform = this.styles.vendor.length ? this.styles.vendor + "Transform" : "transform";
2910	this.tween = new Object();
2911	this.tween.transition = a("transition");
2912	this.tween.css2d = a("transform");
2913	this.tween.css3d = a("perspective");
2914	this.tween.complete = (function() {
2915		if (b.browser.firefox || b.browser.ie) {
2916			return "transitionend"
2917		}
2918		if (b.browser.opera) {
2919			return "oTransitionEnd"
2920		}
2921		return "webkitTransitionEnd"
2922	})();
2923	this.openFullscreen = function(c) {
2924		c = c || __body;
2925		if (c && b.system.fullscreen) {
2926			if (c == __body) {
2927				c.css({top: 0})
2928			}
2929			c.div[b.vendor + "RequestFullScreen"]()
2930		}
2931	};
2932	this.closeFullscreen = function() {
2933		if (b.system.fullscreen) {
2934			document[b.vendor + "CancelFullScreen"]()
2935		}
2936	};
2937	this.getFullscreen = function() {
2938		return document[b.vendor + "IsFullScreen"]
2939	}
2940};
2941
2942var d = new Device();
2943
2944module.exports = d;
2945},{}],8:[function(require,module,exports){
2946var Util = require('./Utils');
2947
2948var Easer = function(_ease) {
2949
2950	var ease = _ease || 1;
2951
2952	var pos = 0,
2953		target = 0,
2954		min = -100000000,
2955		max = 1000000000;
2956	var MAXDELTA = 100000;
2957
2958	var e = {
2959		velocity: 0
2960	};
2961
2962	e.setTarget = function(_target) {
2963
2964		target = _target;
2965	}
2966
2967	e.getTarget = function() {
2968
2969		return target;
2970	}
2971
2972	e.updateTarget = function(delta) {
2973
2974		target += delta;
2975	}
2976
2977	e.setLimits = function(_min, _max) {
2978
2979		min = _min;
2980		max = _max;
2981	}
2982
2983	e.easeVal = function() {
2984
2985		target = Util.clamp(target, min, max);
2986		e.velocity = (target - pos) * ease;
2987		pos += e.velocity;
2988		return pos;
2989	}
2990
2991	e.setEase = function(e) {
2992
2993		ease = e;
2994	}
2995
2996	e.reset = function(val) {
2997
2998		pos = val || 0;
2999		target = val || 0;
3000	}
3001
3002	e.toString = function() {
3003		
3004		return 'min: ' + min + ' / max: ' + max + ' / target: ' + target + ' / pos: ' + pos;
3005	}
3006
3007	return e;
3008}
3009
3010module.exports = Easer;
3011},{"./Utils":22}],9:[function(require,module,exports){
3012
3013function serialize(form) {
3014	if (!form || form.nodeName !== "FORM") {
3015		return;
3016	}
3017	var i, j, q = [];
3018	for (i = form.elements.length - 1; i >= 0; i = i - 1) {
3019		if (form.elements[i].name === "") {
3020			continue;
3021		}
3022		switch (form.elements[i].nodeName) {
3023		case 'INPUT':
3024			switch (form.elements[i].type) {
3025			case 'text':
3026			case 'email':
3027			case 'hidden':
3028			case 'password':
3029			case 'button':
3030			case 'reset':
3031			case 'submit':
3032				q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
3033				break;
3034			case 'checkbox':
3035			case 'radio':
3036				if (form.elements[i].checked) {
3037					q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
3038				}						
3039				break;
3040			case 'file':
3041				break;
3042			}
3043			break;			 
3044		case 'TEXTAREA':
3045			q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
3046			break;
3047		case 'SELECT':
3048			switch (form.elements[i].type) {
3049			case 'select-one':
3050				q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
3051				break;
3052			case 'select-multiple':
3053				for (j = form.elements[i].options.length - 1; j >= 0; j = j - 1) {
3054					if (form.elements[i].options[j].selected) {
3055						q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value));
3056					}
3057				}
3058				break;
3059			}
3060			break;
3061		case 'BUTTON':
3062			switch (form.elements[i].type) {
3063			case 'reset':
3064			case 'submit':
3065			case 'button':
3066				q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
3067				break;
3068			}
3069			break;
3070		}
3071	}
3072	return q.join("&");
3073}
3074
3075module.exports = serialize;
3076},{}],10:[function(require,module,exports){
3077
3078
3079
3080var Class = require('./oop/Class');
3081var View = require('./View');
3082
3083var $ = require('./DOM');
3084var Config = require('./../Config');
3085
3086var Ticker = require('./../components/Ticker');
3087
3088var winHeight = window.innerHeight;
3089var winWidth = window.innerWidth;
3090
3091var mouse = {
3092	x: winWidth / 2,
3093	y: winHeight / 2
3094};
3095
3096var mouseTarget = {
3097	x: mouse.x,
3098	y: mouse.y
3099};
3100
3101var onMouseMove = function(e) {
3102
3103	mouse.x = (winWidth / 2) - e.pageX;
3104	mouse.y = (winHeight / 2) - e.pageY;
3105};
3106
3107var Hero = new Class({
3108
3109	name: 'hero',
3110	Extends: View,
3111	template: "<img src=\"{{ config.cdn }}images/history/hero/{{ hero.coverImage }}\" alt=\"\" class=\"cover-image\" />\n\n<div class=\"scroll\">\n\t<div>Scroll</div>\n\t<div>\n\t\t<span>&darr;</span>\n\t\t<span>&darr;</span>\n\t</div>\n</div>\n\n<video src=\"{{ config.cdn }}video/flicker.mp4\" loop autoplay></video>\n<img src=\"{{ config.cdn }}images/history/hero/{{ hero.image }}\" alt=\"\" class=\"background-image\" />",
3112
3113	initialize: function( data ) {
3114
3115		var _this = this;
3116
3117		data.config = Config;
3118
3119		this.render(data);
3120
3121		this.addListeners();
3122
3123		this.coverImg = $.select('.cover-image', this.div);
3124		this.backgroundImg = $.select('.background-image', this.div);
3125
3126		//- build number tickers for years
3127		this.ticker1 = new Ticker(data.dates.from);
3128		this.ticker2 = new Ticker(data.dates.to);
3129
3130		$.append(this.ticker1.div, this.div);
3131		$.append(this.ticker2.div, this.div);
3132	},
3133
3134	addListeners: function() {
3135
3136		$.on(document, "mousemove", onMouseMove);
3137	},
3138
3139	removeListeners: function() {
3140
3141		$.off(document, 'mousemove', onMouseMove);
3142	},
3143
3144	onRender: function(scr) {
3145
3146		mouseTarget.x += (mouseTarget.x - mouse.x) * -0.075;
3147		mouseTarget.y += (mouseTarget.y - mouse.y) * -0.075;
3148
3149		$.css(this.div, {
3150			transform: 'translateY(' + scr * 0.35 + 'px)'
3151		});
3152
3153		var x = mouseTarget.x / -100;
3154		var y = mouseTarget.y / -100;
3155
3156		var op = 1 - ((scr / 10) / -100);
3157
3158		$.css(this.coverImg, {
3159			marginTop: (y * 1.5) + (scr * 0.175),
3160			marginLeft: x * 1.5,
3161			opacity: op
3162		});
3163
3164		$.css(this.backgroundImg, {
3165			marginTop: y * 1,
3166			marginLeft: x * 1
3167		});
3168
3169		$.transform(this.ticker1.div, {
3170			y: (y * 3) + (scr * 0.175),
3171			x: x * 3
3172		}).css(this.ticker1.div, {
3173			opacity: op
3174		});
3175
3176		$.transform(this.ticker2.div, {
3177			y: (y * 3) + (scr * 0.175),
3178			x: x * 3
3179		}).css(this.ticker2.div, {
3180			opacity: op
3181		});
3182	},
3183
3184	animateIn: function() {
3185
3186		this.ticker1.animateIn();
3187		this.ticker2.animateIn();		
3188	},
3189
3190	animateOut: function() {
3191
3192		this.removeListeners();
3193	},
3194
3195	resize: function( w, h ) {
3196
3197		$.css(this.div, {
3198			width: w,
3199			height: h
3200		});
3201	}
3202});
3203
3204module.exports = Hero;
3205},{"./../Config":1,"./../components/Ticker":21,"./DOM":6,"./View":23,"./oop/Class":28}],11:[function(require,module,exports){
3206
3207
3208
3209var Class = require('./oop/Class');
3210var View = require('./View');
3211
3212var $ = require('./DOM');
3213var Config = require('./../Config');
3214
3215var ShuffleLetters = require('./ShuffleLetters')();
3216
3217var HistoryTimeline = new Class({
3218
3219	name: 'history-timeline',
3220	Extends: View,
3221	template: "<div class=\"indicator\"></div>\n<div class=\"year\"></div>\n<div class=\"title\"></div>",
3222	active: false,
3223
3224	initialize: function( data ) {
3225
3226		this.render();
3227
3228		this.bar = $.select('.bar', this.div);
3229		this.year = $.select('.year', this.div);
3230		this.title = $.select('.title', this.div);
3231		this.indicator = $.select('.indicator', this.div);
3232	},
3233
3234	update: function( _year, _title ) {
3235
3236		ShuffleLetters(this.year, _year);
3237		ShuffleLetters(this.title, _title);
3238	},
3239
3240	animateIn: function() {
3241
3242		
3243	},
3244
3245	animateOut: function() {
3246
3247		this.removeListeners();
3248	}
3249});
3250
3251module.exports = HistoryTimeline;
3252},{"./../Config":1,"./DOM":6,"./ShuffleLetters":18,"./View":23,"./oop/Class":28}],12:[function(require,module,exports){
3253var Loader = {
3254
3255	loadText: function(path, onLoadedFunc) {
3256
3257		var request = new XMLHttpRequest();
3258		request.open("GET", path);
3259
3260		request.onreadystatechange = function() {
3261			
3262			if (request.readyState == 4) {
3263				onLoadedFunc.call(null, request.responseText);
3264			}
3265		};
3266
3267		request.send();
3268	},
3269
3270	post: function(path, data, onLoadedFunc) {
3271
3272		if( typeof data === 'function' && onLoadedFunc === 'undefined' ) {
3273
3274			onLoadedFunc = data;
3275			data = {};
3276		}
3277
3278		var request = new XMLHttpRequest();
3279
3280		request.onreadystatechange = function() {
3281
3282			if (request.readyState == 4) {
3283				var r = JSON.parse(request.responseText)
3284				onLoadedFunc.call(null, r);
3285			}
3286		};
3287
3288		request.open("POST", path);
3289		request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
3290
3291		request.send(data)
3292	},
3293
3294	loadJSON: function(path, onLoadedFunc) {
3295
3296		Loader.loadText(path, function(text) {
3297			onLoadedFunc(JSON.parse(text));
3298		});
3299	},
3300
3301	loadImage:function(src, callback) {
3302
3303		var img = new Image();
3304		img.onload = callback(img);
3305		setTimeout(function() {
3306			img.src = src;
3307		}, 10);
3308	}
3309
3310};
3311
3312module.exports = Loader;
3313},{}],13:[function(require,module,exports){
3314
3315
3316var Velocity = require('velocity-animate');
3317var UIPack = require('velocity-animate/velocity.ui');
3318var Class = require('./oop/Class');
3319var View = require('./../components/View');
3320var $ = require('./../components/DOM');
3321var Util = require('./Utils');
3322var Device = require('./Device');
3323
3324var NavController = require('./NavController');
3325var Config = require('./../Config');
3326var data = require('./../Data').navigation;
3327
3328var Nav = new Class({
3329
3330	name: "nav",
3331	Extends: View,
3332	active: false,
3333	template: "\n<div class=\"content\">\n\n\t{{ #sections }}\n\n\t\t<div class=\"section {{ #secondary }}section-secondary{{ /secondary }} {{ key }}\">\n\t\t\t<a href=\"{{ url }}\">{{{ title }}}</a>\n\t\t</div>\n\n\t{{ /sections }}\n\n\t<ul class=\"social\">\n\t\t\n\t\t{{ #social }}\n\n\t\t\t<li class=\"{{ key }}\">\n\t\t\t\t<a href=\"{{ url }}\" target=\"_blank\">\n\t\t\t\t\t<img src=\"{{ config.cdn }}images/icn-{{ key }}.png\" alt=\"St Louis Brows: {{ key }}\" />\n\t\t\t\t\t<img src=\"{{ config.cdn }}images/icn-{{ key }}-hover.png\" alt=\"St Louis Brows: {{ key }}\" />\n\t\t\t\t</a>\n\t\t\t</li>\n\n\t\t{{ /social }}\n\n\t</ul>\n\t\n</div>",
3334
3335	initialize: function( onComplete ) {
3336
3337		data.config = Config;
3338
3339		this.Controller = new NavController(this);
3340		this.render(data, document.body, true);
3341
3342		this.Controller.animateIn();
3343
3344		this.Sections = $.select('.section, .social', this.div);
3345
3346		Velocity.hook(this.div, "transform-origin", "top center");
3347	},
3348
3349	animateIn: function() {
3350
3351		this.active = true;
3352
3353		this.dark = $.hasClass(this.Controller.div, 'dark');
3354
3355		$.css(this.div, {
3356			display: 'block'
3357		});
3358
3359		var controllers = $.select('.nav-controller', document.body);
3360		$.addClass('dark', controllers);
3361
3362		Velocity(this.Sections, "transition.fadeIn",
3363		{
3364			stagger: 100,
3365			duration: 400,
3366			display: 'block',
3367			delay: 500
3368		});
3369
3370		Velocity(this.div, {
3371			opacity: [ 1, 0 ],
3372			translateY: [ 0, 25 ]
3373		}, {
3374			duration: 1200,
3375			delay: 500,
3376			easing: 'easeOutCubic'
3377		});
3378
3379		Velocity(Stage, {
3380			blur: ( Device.system.touch ) ? 0 : [ 10, 0 ],
3381			scale: ( Device.system.touch ) ? 1 : 1.01,
3382			opacity: ( Device.system.touch ) ? 0.15 : 0.25,
3383			translateZ: 0
3384		}, {
3385			duration: 2000,
3386			easing: 'easeOutCubic'
3387		});
3388	},
3389
3390	animateOut: function() {
3391
3392		var controller = $.select('.nav-controller');
3393
3394		if( this.dark ) {
3395			$.addClass('dark', controller);
3396		} else {
3397			$.removeClass(controller, 'dark');
3398		}
3399		
3400		$.removeClass(controller, 'active');
3401
3402		this.active = false;
3403
3404		Velocity(this.Sections, "transition.fadeOut",
3405		{
3406			stagger: 50,
3407			duration: 250,
3408			display: 'block'
3409		});
3410
3411		Velocity(this.div, {
3412			opacity: 0,
3413			translateY: 10
3414		}, {
3415			duration: 350,
3416			display: 'none'
3417		});
3418
3419		Velocity(Stage, {
3420			blur: 0,
3421			opacity: 1,
3422			scale: 1,
3423			translateZ: 0
3424		}, {
3425			duration: 1000,
3426			easing: 'linear'
3427		});
3428	}
3429});
3430
3431module.exports = Nav;
3432},{"./../Config":1,"./../Data":2,"./../components/DOM":6,"./../components/View":23,"./Device":7,"./NavController":14,"./Utils":22,"./oop/Class":28,"velocity-animate":54,"velocity-animate/velocity.ui":55}],14:[function(require,module,exports){
3433
3434
3435var Velocity = require('velocity-animate');
3436var Class = require('./oop/Class');
3437var View = require('./../components/View');
3438var $ = require('./../components/DOM');
3439var Device = require('./../components/Device');
3440
3441var Nav = require('./Nav');
3442var Config = require('./../Config');
3443var _data = require('./../Data');
3444
3445var NavController = new Class({
3446
3447	name: "nav-controller",
3448	template: "\n<div class=\"icon\">\n\t<span class=\"ball\"></span>\n\t<span class=\"bars\">\n\t\t<div></div>\n\t\t<div></div>\n\t\t<div></div>\n\t</span>\n\t<span class=\"close\">\n\t\t<div></div>\n\t\t<div></div>\n\t</span>\n</div>\n\n<div class=\"text\">\n\tMenu\n</div>",
3449	Extends: View,
3450
3451	initialize: function( parent ) {
3452
3453		this.render(_data, document.body, true);
3454
3455		Velocity.hook(this.div, "opacity", 0);
3456
3457		setTimeout(this.addListeners( parent ), 10000);
3458	},
3459
3460	addListeners: function( parent ) {
3461
3462		var _this = this;
3463		var icon = $.select('.icon', this.div);
3464		var items = $.select('span', icon);
3465		var text = $.select('.text', this.div);
3466
3467		function handler(e) {
3468
3469			e.preventDefault();
3470
3471			if( parent.active ) {
3472				parent.animateOut();
3473				$.removeClass(_this.div, 'active');
3474				parent.active = false;
3475			}
3476			else {
3477				parent.animateIn();
3478				$.addClass('active', _this.div);
3479				parent.active = true;
3480			}
3481		}
3482
3483		if( Device.system.touch ) {
3484			$.on(this.div, 'touchend', handler);
3485		} else {
3486			$.on(this.div, 'click', handler);
3487		}
3488	},
3489
3490	animateIn: function() {
3491
3492		var t = $.select('.title-text', document.body);
3493
3494		Velocity(this.div, {
3495			opacity: [ 1, 0 ]
3496		}, {
3497			duration: 1200,
3498			easing: 'easeOutCubic',
3499			delay: 500
3500		});
3501
3502		Velocity(t, {
3503			opacity: [ 1, 0 ]
3504		}, {
3505			duration: 1200,
3506			easing: 'easeOutCubic',
3507			delay: 500
3508		});
3509	}
3510});
3511
3512module.exports = NavController;
3513},{"./../Config":1,"./../Data":2,"./../components/DOM":6,"./../components/Device":7,"./../components/View":23,"./Nav":13,"./oop/Class":28,"velocity-animate":54}],15:[function(require,module,exports){
3514
3515
3516
3517var Class = require('./oop/Class');
3518var View = require('./View');
3519
3520var $ = require('./DOM');
3521var Loader = require('./Loader');
3522var Config = require('./../Config');
3523var Velocity = require('velocity-animate');
3524var Device = require('./../components/Device');
3525
3526var Overlay = new Class({
3527
3528	Extends: View,
3529	name: 'overlay',
3530	template: '',
3531	templates: {
3532		players: "<div class=\"align\">\n\n\t<div class=\"inner\">\n\n\t\t<div class=\"close\">&times;</div>\n\n\t\t<h2>{{{ firstName }}} {{{ lastName }}}</h2>\n\t\t{{{ bio }}}\n\n\t\t<hr />\n\n\t\t<div class=\"stats grid\">\n\n\t\t\t<div>\n\t\t\t\t<h5>Position</h5>\n\t\t\t\t<p>{{ details.position }}</p>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h5>Bats</h5>\n\t\t\t\t<p>{{ details.bats }}</p>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h5>Throws</h5>\n\t\t\t\t<p>{{ details.arm }}</p>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h5>Height</h5>\n\t\t\t\t<p>{{ details.height.feet }}&rsquo; {{ details.height.inches }}
3532&rdquo;</p>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h5>Weight</h5>\n\t\t\t\t<p>{{ details.weight }}</p>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h5>Hometown</h5>\n\t\t\t\t<p>{{ details.city }}</p>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h5>Born</h5>\n\t\t\t\t<p>{{ details.born.month }}/{{ details.born.day }}/{{ details.born.year }}</p>\n\t\t\t</div>\n\n\t\t</div>\n\n\t</div>\n\n\t<div class=\"url\">\n\t\t<a href=\"{{ url }}\" target=\"_blank\">More Stats &rarr;</a>\n\t</div>\n\n</div>",
3533		'history-section': "<div class=\"align\">\n\n\t<div class=\"inner\">\n\n\t\t<div class=\"close\">&times;</div>\n\t\t<h2>{{{ title }}}</h2>\n\t\t{{{ body }}}\n\n\t</div>\n\n</div>"
3534	},
3535	active: false,
3536
3537	init: function( parent ) {
3538
3539		this.parent = parent;
3540
3541		Velocity.hook(this.div, "opacity", 0);
3542
3543		$.append(this.div, parent.div);
3544	},
3545
3546	populate: function( playerData, tpl ) {
3547
3548		this.template = this.templates[ tpl ];
3549		var _this = this;
3550
3551		this.render(playerData);
3552		this.content = $.select('.inner', this.div);
3553		this.items = $.select('.stats > div', this.div);
3554		this.mouseBug = $.select('.mouse-bug', this.div);
3555		this.closeBtn = $.select('.close', this.div);
3556
3557		setTimeout(function() {
3558			_this.resize();
3559		}, 100);
3560
3561		this.animateIn();
3562	},
3563
3564	animateIn: function() {
3565
3566		var url = $.select('.url', this.div);
3567		var controller = $.select('.nav-controller');
3568
3569		$.removeClass(controller, 'dark');
3570
3571		Velocity(this.div, {
3572			opacity: 1,
3573			translateZ: 0
3574		}, {
3575			display: 'block',
3576			easing: 'easeOutCubic',
3577			duration: 500
3578		});
3579
3580		Velocity(this.content, {
3581			blur: [ 0, 5 ],
3582			top: [ 0, 35 ],
3583			opacity: [ 1, 0 ],
3584			translateZ: 0
3585		}, {
3586			easing: 'easeOutCubic',
3587			duration: 1200
3588		});
3589
3590		Velocity(this.items, "transition.slideUpIn", {
3591			stagger: 100
3592		});
3593
3594		Velocity(this.closeBtn, {
3595			opacity: [ 1, 0 ]
3596		}, {
3597			duration: 500,
3598			easing: "easeOutCubic"
3599		});
3600
3601		Velocity(url, {
3602			opacity: [ 1, 0 ]
3603		}, {
3604			duration: 750,
3605			delay: 1000,
3606			easing: "easeOutCubic"
3607		});
3608	},
3609
3610	animateOut: function() {
3611
3612		Velocity(this.div, {
3613			opacity: 0
3614		}, {
3615			display: 'none',
3616			easing: 'easeOutCubic',
3617			duration: 500
3618		});
3619
3620		var controller = $.select('.nav-controller');
3621
3622		$.addClass('dark', controller);
3623	},
3624
3625	resize: function( w, h ) {
3626
3627		
3628	}
3629});
3630
3631module.exports = Overlay;
3632},{"./../Config":1,"./../components/Device":7,"./DOM":6,"./Loader":12,"./View":23,"./oop/Class":28,"velocity-animate":54}],16:[function(require,module,exports){
3633
3634
3635var Config = require('./../Config');
3636var Class = require('./oop/Class');
3637var hasNative = 'addEventListener' in ( new Image() );
3638
3639function checkProgress( src, image ) {
3640
3641	// intermediate checker for queue remaining. not exported.
3642	// called on preLoader instance as scope
3643	var args = [];
3644	var o = this.options;
3645
3646	// call onProgress
3647	o.onProgress && src && o.onProgress.call(this, src, image, this.completed.length);
3648
3649	if (this.completed.length + this.errors.length === this.queue.length) {
3650		args.push(this.completed);
3651		this.errors.length && args.push(this.errors);
3652		o.onComplete.apply(this, args);
3653	}
3654
3655	return this;
3656}
3657
3658var Preloader = new Class({
3659
3660	initialize: function(images, options) {
3661
3662		this.options = {
3663			pipeline: false,
3664			auto: true,
3665			prefetch: false,
3666			onComplete: function() {}
3667		};
3668
3669		options && typeof options == 'object' && this.setOptions(options);
3670
3671		this.addQueue(images);
3672		this.queue.length && this.options.auto && this.processQueue();
3673	},
3674
3675	animateIn: function( onComplete ) {
3676
3677
3678	},
3679
3680	animateOut: function( onComplete ) {
3681
3682		var _this = this;
3683
3684		Velocity(this.div, {
3685			opacity: 0
3686		}, {
3687			duration: 500,
3688			complete: function() {
3689
3690				_this.engine.stop();
3691				onComplete();
3692			}
3693		});
3694	},
3695
3696	setOptions: function( options ) {
3697		
3698		// shallow copy
3699		var o = this.options, key;
3700
3701		for (key in options) options.hasOwnProperty(key) && (o[key] = options[key]);
3702
3703		return this;
3704	},
3705
3706	addQueue: function( images ) {
3707		
3708		this.queue = images;
3709
3710		return this;
3711	},
3712
3713	reset: function() {
3714
3715		this.completed = [];
3716		this.errors = [];
3717
3718		return this;
3719	},
3720
3721	addEvents: function(image, src, index) {
3722
3723		var _this = this;
3724		var o = this.options;
3725
3726		var cleanup = function() {
3727
3728				this.removeEventListener('error', abort);
3729				this.removeEventListener('abort', abort);
3730				this.removeEventListener('load', load);
3731			};
3732
3733		var abort = function() {
3734
3735				cleanup.call(this);
3736
3737				_this.errors.push(src);
3738				o.onError && o.onError.call(_this, src);
3739				checkProgress.call(_this, src);
3740				o.pipeline && _this.loadNext(index);
3741			};
3742
3743		var load = function() {
3744
3745				cleanup.call(this);
3746
3747				// store progress. this === image
3748				_this.completed.push(src); // this.src may differ
3749				checkProgress.call(_this, src, this);
3750				o.pipeline && _this.loadNext(index);
3751			};
3752
3753		image.addEventListener('error', abort, false);
3754		image.addEventListener('abort', abort, false);
3755		image.addEventListener('load', load, false);
3756
3757		return this;
3758	},
3759
3760	load: function( src, index ) {
3761
3762		var image = new Image;
3763
3764		this.addEvents(image, Config.cdn + src, index);
3765
3766		// actually load
3767		image.src = Config.cdn + src;
3768
3769		return this;
3770	},
3771
3772	loadNext: function( index ) {
3773
3774		// when pipeline loading is enabled, calls next item
3775		index++;
3776		this.queue[index] && this.load(this.queue[index], index);
3777
3778		return this;
3779	},
3780
3781	processQueue: function() {
3782
3783		// runs through all queued items.
3784		var i = 0,
3785			queue = this.queue,
3786			len = queue.length;
3787
3788		// process all queue items
3789		this.reset();
3790
3791		if (!this.options.pipeline)
3792			for (; i < len; ++i) this.load(queue[i], i);
3793		else this.load(queue[0], 0);
3794
3795		return this;
3796	}
3797})
3798
3799module.exports = Preloader;
3800},{"./../Config":1,"./oop/Class":28}],17:[function(require,module,exports){
3801var routes = require( 'routes' );
3802
3803var noop = function() {};
3804
3805function router( settings ) {
3806
3807	if( !( this instanceof router ) ) {
3808
3809		return new router( settings );
3810	}
3811
3812	var s = this.s = settings || {};
3813
3814	s.postHash = s.postHash || '';
3815	s.onRoute = s.onRoute || function() {};
3816
3817	this.router = routes();
3818}
3819
3820router.prototype = {
3821
3822	init: function() {
3823
3824		var s = this.s;
3825
3826		// figure out a start section
3827		if( s[ '/' ] === undefined ) {
3828
3829			// find the first path which would be a section
3830			for( var i in s ) {
3831
3832				if( i[ 0 ] == '/' ) {
3833
3834					s.start = i;
3835
3836					break;
3837				}
3838			}
3839		} else {
3840
3841			s.start = '/';
3842		}
3843
3844
3845		// now setup routes
3846		for( var i in s ) {
3847
3848			if( i[ 0 ] == '/' ) {
3849
3850				this.router.addRoute( i, noop );
3851			}
3852		}
3853
3854		window.addEventListener( 'hashchange', this.onURL.bind( this ) )
3855
3856		// force a hash change to start things up
3857		this.onURL();
3858
3859		return this;
3860	},
3861
3862	add: function( route, section ) {
3863
3864		var s = this.s;
3865
3866		s[ route ] = section;
3867
3868		return this;
3869	},
3870
3871	go: function( routeStr ) {
3872
3873		if( routeStr[ 0 ] != '/' )
3874			routeStr = '/' + routeStr;
3875
3876		var routeData = this.getRouteData( routeStr ),
3877			section = this.getSection( routeData );
3878
3879		// if this is not a section descriptor or it is a descriptor and we should updateURL
3880		if( this.useURL( section ) )
3881			window.location.hash = this.s.postHash + routeStr;
3882		else
3883			this.doRoute( routeData, section );
3884	},
3885
3886	doRoute: function( routeData, section ) {
3887
3888		var s = this.s;
3889
3890		if( section ) {
3891
3892			// check if this is a redirect
3893			if( typeof section == 'string' ) {
3894
3895				this.go( section );
3896			// otherwise treat it as a regular section
3897			} else {
3898
3899				// if this is a object definition vs a section definition
3900				if( section.section ) {
3901
3902					s.onRoute( section.section, routeData );
3903				// this is a regular section or array
3904				} else {
3905
3906					s.onRoute( section, routeData );
3907				}
3908			}
3909				
3910		} else if( s[ '404' ] ) {
3911
3912			s.onRoute( s[ '404' ], routeData );
3913		}
3914	},
3915
3916	getRouteData: function( routeStr ) {
3917
3918		return this.router.match( routeStr );
3919	},
3920
3921	getSection: function( routeData ) {
3922
3923		if( routeData ) {
3924
3925			return this.s[ routeData.route ];
3926		} else {
3927
3928			return null;
3929		}
3930	},
3931
3932	useURL: function( section ) {
3933
3934		return section && 
3935			   ( section.section === undefined ||  // if this is not a section descriptor update url
3936			   ( section.section && section.useURL || section.useURL === undefined ) ) //is descriptor and has useURL or undefined
3937	},
3938
3939	onURL: function() {
3940
3941		var routeStr = '/',
3942			routeData, section;
3943
3944		if( window.location.hash != '' ) {
3945
3946			routeStr = window.location.hash.substr( 1 + this.s.postHash.length );
3947		}
3948
3949		routeData = this.getRouteData( routeStr );
3950		section = this.getSection( routeData );
3951
3952		// see if we can deep link into this section
3953		if( this.useURL( section ) )
3954			this.doRoute( routeData, section );
3955		// we should 404. Pass null value for section for the 404 to come up
3956		else
3957			this.doRoute( routeData, null );
3958	}
3959};
3960
3961module.exports = router;
3962},{"routes":52}],18:[function(require,module,exports){
3963var $ = require('./DOM');
3964
3965function randomChar(type){
3966	var pool = "";
3967	
3968	if (type == "lowerLetter"){
3969		pool = "abcdefghijklmnopqrstuvwxyz0123456789";
3970	}
3971	else if (type == "upperLetter"){
3972		pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
3973	}
3974	else if (type == "symbol"){
3975		pool = "1234567890";
3976	}
3977	
3978	var arr = pool.split('');
3979	return arr[Math.floor(Math.random()*arr.length)];
3980}
3981
3982
3983var ShuffleLetters = function( el, _text ) {
3984	
3985	var options = {
3986		"step"		: 12,				// How many times should the letters be changed
3987		"fps"		: 30,				// Frames Per Second
3988		"text"		: "", 				// Use this text instead of the contents
3989		"callback"	: function() {}		// Run once the animation is complete
3990	};
3991
3992	return function(_el, _text) {
3993
3994		var el = $._bonzo(_el),
3995			str = "";
3996
3997		options.text = _text;
3998
3999		// Preventing parallel animations using a flag;
4000
4001		if( el.data('animated') ){
4002			return true;
4003		}
4004		
4005		el.data( 'animated', true );
4006		
4007		
4008		if( options.text ) {
4009			str = options.text.split('');
4010		}
4011		else {
4012			str = el.text().split('');
4013		}
4014		
4015		// The types array holds the type for each character;
4016		// Letters holds the positions of non-space characters;
4017		
4018		var types = [],
4019			letters = [];
4020
4021		// Looping through all the chars of the string
4022		
4023		for( var i = 0; i < str.length; i ++ ) {
4024			
4025			var ch = str[i];
4026			
4027			if( ch == " " ){
4028				types[i] = "space";
4029				continue;
4030			}
4031			else if( /[a-z]/.test(ch) ){
4032				types[i] = "lowerLetter";
4033			}
4034			else if( /[A-Z]/.test(ch) ){
4035				types[i] = "upperLetter";
4036			}
4037			else {
4038				types[i] = "symbol";
4039			}
4040			
4041			letters.push(i);
4042		}
4043		
4044		$.html(el, "");			
4045
4046		// Self executing named function expression:
4047		
4048		(function shuffle(start) {
4049		
4050			// This code is run options.fps times per second
4051			// and updates the contents of the page element
4052				
4053			var i,
4054				len = letters.length, 
4055				strCopy = str.slice(0);	// Fresh copy of the string
4056				
4057			if( start > len ){
4058				
4059				// The animation is complete. Updating the
4060				// flag and triggering the callback;
4061				
4062				el.data('animated',false);
4063				options.callback(el);
4064				return;
4065			}
4066			
4067			// All the work gets done here
4068			for(i=Math.max(start,0); i < len; i++){
4069
4070				// The start argument and options.step limit
4071				// the characters we will be working on at once
4072				
4073				if( i < start+options.step){
4074					// Generate a random character at thsi position
4075					strCopy[letters[i]] = randomChar(types[letters[i]]);
4076				}
4077				else {
4078					strCopy[letters[i]] = "";
4079				}
4080			}
4081			
4082			el.text(strCopy.join(""));
4083			
4084			setTimeout(function(){
4085				
4086				shuffle(start+1);
4087				
4088			},1000/options.fps);
4089			
4090		})(-options.step);
4091		
4092
4093	};
4094};
4095
4096module.exports = ShuffleLetters;
4097},{"./DOM":6}],19:[function(require,module,exports){
4098
4099
4100var Class = require('./oop/Class');
4101
4102var Easer = require('./Easer');
4103var VirtualScroll = require('./VirtualScroll')();
4104var Loop = require('raf-loop');
4105
4106var SmoothScroll = new Class({
4107
4108	initialize: function( callback, easeVal ) {
4109
4110		easeVal = easeVal || 0.15;
4111
4112		this.callback = null;
4113		this.callback = callback;
4114		this.easer = new Easer( easeVal );
4115		this.engine = new Loop( this.onRender.bind(this) );
4116	},
4117
4118	setLimits: function(_min, _max) {
4119
4120		this.easer.setLimits(_min, _max);
4121	},
4122
4123	addListeners: function() {
4124
4125		VirtualScroll.on( this.onScroll.bind(this) );
4126	},
4127
4128	removeListeners: function() {
4129
4130		VirtualScroll.off( this.onScroll.bind(this) );
4131	},
4132
4133	onScroll: function(e) {
4134
4135		if( e.originalEvent.type && e.originalEvent.type !== 'keydown' ) e.originalEvent.preventDefault();
4136
4137		var d = (e.deltaX + e.deltaY) * 0.5;
4138		this.easer.updateTarget(d);
4139	},
4140
4141	onRender: function(delta) {
4142
4143		var scr = this.easer.easeVal();
4144		this.callback(scr, delta);
4145	},
4146
4147	startRender: function() {
4148
4149		this.addListeners();
4150		this.engine.start();
4151	},
4152
4153	stopRender: function() {
4154
4155		this.engine.stop();
4156		this.removeListeners();
4157	},
4158
4159	setTarget: function( target ) {
4160
4161		this.easer.setTarget( target );
4162	}
4163});
4164
4165module.exports = SmoothScroll;
4166},{"./Easer":8,"./VirtualScroll":26,"./oop/Class":28,"raf-loop":48}],20:[function(require,module,exports){
4167
4168var Class = require('./oop/Class');
4169
4170var Easer = require('./Easer');
4171var VirtualScroll = require('./VirtualScroll')();
4172var Loop = require('raf-loop');
4173var Util = require('./Utils');
4174
4175var lastAnimation = null;
4176var timeNow = null;
4177var waitTime = 1000;
4178var index = 0;
4179
4180var SnappyScroll = new Class({
4181
4182	initialize: function( callback, easeVal, wait ) {
4183
4184		easeVal = easeVal || 0.15;
4185
4186		if( wait ) waitTime = wait;
4187
4188		this.callback = callback;
4189		this.easer = new Easer( easeVal );
4190		this.engine = new Loop( this.onRender.bind(this) );
4191		this.scrAmt = 0;
4192	},
4193
4194	setIndex: function( idx ) {
4195
4196		var e = {
4197			deltaX: (index < idx) ? -1 : 1,
4198			deltaY: 0,
4199			x: 0,
4200			Y: 0,
4201			originalEvent: {
4202				type: null
4203			}
4204		}
4205
4206		this.onScroll(e);
4207	},
4208
4209	setMaxIndex: function( i ) {
4210
4211		this.maxIndex = parseInt(i) - 1;
4212	},
4213
4214	setWidth: function( _width ) {
4215
4216		this.scrAmt = _width;
4217	},
4218
4219	setLimits: function(_min, _max) {
4220
4221		this.easer.setLimits(_min, _max);
4222	},
4223
4224	addListeners: function() {
4225
4226		VirtualScroll.on( this.onScroll.bind(this) );
4227	},
4228
4229	removeListeners: function() {
4230
4231		VirtualScroll.off( this.onScroll.bind(this) );
4232	},
4233
4234	onScroll: function(e) {
4235
4236		if( e.originalEvent.type && e.originalEvent.type !== 'keydown' ) e.originalEvent.preventDefault();
4237
4238		timeNow = new Date().getTime();
4239
4240		if (timeNow - lastAnimation < waitTime) {
4241			
4242			return false;
4243		} else {
4244
4245			// update scroll position here
4246			var a;
4247			var b = this.easer.getTarget();
4248			var amtX = Math.abs( e.deltaX );
4249			var amtY = Math.abs( e.deltaY );
4250
4251			if( amtX > amtY ) {
4252
4253				a = e.deltaX < 0 ? this.scrAmt * -1 : this.scrAmt;
4254				(e.deltaX < 0) ? (index = index + 1) : (index = index - 1);
4255			} else if( amtY > amtX ) {
4256
4257				a = e.deltaY < 0 ? this.scrAmt * -1 : this.scrAmt;
4258				(e.deltaY < 0) ? (index = index + 1) : (index = index - 1);
4259			}
4260
4261			index = Util.clamp(index, 0, this.maxIndex);
4262			
4263			b += a;
4264
4265			this.easer.setTarget(b);
4266
4267			if( this.onScrollUpdate )
4268				this.onScrollUpdate( index );
4269		}
4270
4271		lastAnimation = timeNow;
4272	},
4273
4274	onRender: function(delta) {
4275
4276		var scr = this.easer.easeVal();
4277		this.callback(scr, delta);
4278	},
4279
4280	startRender: function() {
4281
4282		this.addListeners();
4283		this.engine.start();
4284
4285		if( this.onScrollUpdate )
4286			this.onScrollUpdate( index );
4287	},
4288
4289	stopRender: function() {
4290
4291		this.engine.stop();
4292		this.removeListeners();
4293	},
4294
4295	setTarget: function( target ) {
4296
4297		this.easer.setTarget( target );
4298	}
4299});
4300
4301module.exports = SnappyScroll;
4302},{"./Easer":8,"./Utils":22,"./VirtualScroll":26,"./oop/Class":28,"raf-loop":48}],21:[function(require,module,exports){
4303
4304
4305var Class = require('./oop/Class');
4306var View = require('./View');
4307
4308var $ = require('./DOM');
4309var Velocity = require('velocity-animate');
4310
4311var Ticker = new Class({
4312
4313	name: 'ticker',
4314	Extends: View,
4315
4316	initialize: function( _num ) {
4317
4318		this.div = document.createElement('div');
4319		this.div.className = 'ticker';
4320
4321		var numbers = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ].join('\n');
4322		var num = '<span>' + numbers + '</span>';
4323		var tpl = '<div class="row row-top">' + num + num + '</div><div class="row row-bottom">' + num + num + '</div>';
4324
4325		this.div.innerHTML = tpl;
4326
4327		this.arr = _num.toString().split('');
4328	},
4329
4330	animateIn: function() {
4331
4332		var _this = this;
4333		var el = $.select('span', this.div);
4334
4335		for( var i = 0; i < this.arr.length; i ++ ) {
4336
4337			var amt = parseInt(this.arr[ i ]) * -10 + '%';
4338
4339			Velocity(el[ i ], {
4340				translateY: amt
4341			}, {
4342				duration: 1000,
4343				delay: (100 * i) + 250,
4344				easing: 'easeOutCubic'
4345			});
4346		}
4347	},
4348
4349	animateOut: function() {
4350
4351
4352	}
4353});
4354
4355module.exports = Ticker;
4356},{"./DOM":6,"./View":23,"./oop/Class":28,"velocity-animate":54}],22:[function(require,module,exports){
4357
4358var $ = require('./DOM');
4359
4360var Utils = {
4361
4362	randomChar: function(type){
4363
4364		var pool = "";
4365		
4366		if (type == "lowerLetter"){
4367			pool = "abcdefghijklmnopqrstuvwxyz0123456789";
4368		}
4369		else if (type == "upperLetter"){
4370			pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
4371		}
4372		else if (type == "symbol"){
4373			pool = ",.?/\\(^)![]{}*&^%$#'\"";
4374		}
4375		
4376		var arr = pool.split('');
4377		return arr[Math.floor(Math.random()*arr.length)];
4378	},
4379
4380	clamp: function(value, start, end) {
4381		if(value < start) return start;
4382		else if(value > end) return end;
4383		else return value;
4384	},
4385
4386	scrollCheck: function(el, scr, callback) {
4387
4388		var all = $.select(el);
4389
4390		for (var i = 0; i < all.length; i ++) {
4391			
4392			var _this = all[i];
4393			
4394			if ( $.hasClass(_this, 'active') ) {
4395				continue
4396			}
4397
4398			var top_fifth_of_object = _this.offsetTop + _this.scrollHeight / 3 - 100;
4399			var bottom_of_window = scr + window.innerHeight;
4400
4401			/* If the object is a third over the fold, fade it in */
4402			if( bottom_of_window > top_fifth_of_object ) {
4403				$.addClass(_this, 'active');
4404				callback(_this, i);
4405			}
4406		}
4407	},
4408
4409	debounce: function(func, wait, immediate) {
4410
4411		var timeout;
4412		return function() {
4413			
4414			var context = this, args = arguments;
4415
4416			var later = function() {
4417
4418				timeout = null;
4419				if (!immediate) func.apply(context, args);
4420			};
4421
4422			var callNow = immediate && !timeout;
4423
4424			clearTimeout(timeout);
4425
4426			timeout = setTimeout(later, wait);
4427
4428			if (callNow) func.apply(context, args);
4429		}
4430	},
4431
4432	norm: function(value , min, max) {
4433		//- Normalizes a number from another range into a value between 0 and 1.
4434		return (value - min) / (max - min);
4435	},
4436
4437	splitText: function(el) {
4438
4439		var t = el.innerText;
4440		var arr = t.split('');
4441		var inject = '';
4442
4443		if (arr.length) {
4444
4445			for( var i = 0; i < arr.length; i ++ ) {
4446
4447				var item = arr[ i ];
4448
4449				if( item == ' ' )
4450					item = '&nbsp;';
4451				inject += '<span>' + item + '</span>';
4452			}
4453
4454			el.innerHTML = '';
4455			el.innerHTML = inject;
4456		}
4457	},
4458
4459	randomBtwn: function(minVal, maxVal) {
4460		return minVal + (Math.random() * (maxVal - minVal));
4461	},
4462
4463	truncate: function(str, len) {
4464
4465		//trim the string to the maximum length
4466		var trimmedString = str.substr(0, len);
4467
4468		//re-trim if we are in the middle of a word
4469		trimmedString = trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" ")))
4470
4471		return trimmedString;
4472	}
4473
4474};
4475
4476module.exports = Utils;
4477},{"./DOM":6}],23:[function(require,module,exports){
4478
4479var Class = require('./oop/Class');
4480var Mustache = require('mustache');
4481var bonzo = require('bonzo');
4482
4483var View = new Class({
4484	
4485	initialize: function() {
4486
4487		this.div = document.createElement('div');
4488
4489		if( this.name )
4490			this.div.className = this.name;
4491
4492		if( this.template )
4493			Mustache.parse(this.template);
4494	},
4495
4496	render: function( data, parent, prepend ) {
4497
4498		var html = Mustache.render( this.template, data );
4499		
4500		this.div.innerHTML = html;
4501
4502		if( parent ) {
4503			
4504			if( prepend )
4505				bonzo(parent).prepend(this.div);
4506			else
4507				bonzo(parent).append(this.div);
4508		}
4509	},
4510
4511	destroy: function() {
4512
4513		this.div.parentNode.removeChild( this.div );
4514	}
4515});
4516
4517module.exports = View;
4518},{"./oop/Class":28,"bonzo":41,"mustache":45}],24:[function(require,module,exports){
4519function ViewManager( settings ) {
4520
4521	if( !( this instanceof ViewManager ) )
4522		return new ViewManager( settings );
4523
4524	var s = this.settings = settings || {};
4525	s.overlap = s.overlap === undefined ? true : s.overlap;
4526	this.width = s.width || 1000;
4527	this.height = s.height || 800;
4528
4529	this.currentContent = null;
4530	this.newContent = null;
4531}
4532
4533ViewManager.prototype = {
4534
4535	get overlap() {
4536
4537		return this.settings.overlap;
4538	},
4539
4540	set overlap( value ) {
4541
4542		this.settings.overlap = value;
4543	},
4544
4545	show: function( content, data, onComplete ) {
4546
4547		if( onComplete === undefined && typeof data == 'function' ) {
4548
4549			onComplete = data;
4550			data = null;
4551		}
4552
4553		if( content != this.newContent && content != this.currentContent ) {
4554
4555			if( this.newContent && this.newContent.destroy )
4556				this.newContent.destroy();
4557
4558			this.newContent = content;
4559
4560			if( content.init ) {
4561
4562				if( data )
4563					content.init( data, this.swap.bind( this, this.newContent, onComplete ) );
4564				else
4565					content.init( this.swap.bind( this, this.newContent, onComplete ) );
4566			} else {
4567
4568				this.swap( this.newContent, onComplete );
4569			}
4570		}
4571	},
4572
4573	clear: function( onComplete ) {
4574
4575		if( this.newContent && this.newContent.destroy )
4576			this.newContent.destroy();
4577
4578		if( this.currentContent ) {
4579
4580			var oldOut = function( oldContent ) {
4581
4582				if( oldContent.destroy )
4583					oldContent.destroy();
4584
4585				if( onComplete )
4586					onComplete( oldContent );
4587			}.bind( this, this.currentContent );
4588
4589			if( this.currentContent.animateOut )
4590				this.currentContent.animateOut( oldOut );
4591			else
4592				oldOut();
4593		}
4594	},
4595
4596	resize: function( w, h ) {
4597
4598		var s = this.settings;
4599
4600		s.width = w;
4601		s.height = h;
4602
4603		if( this.currentContent && this.currentContent.resize )
4604			this.currentContent.resize( w, h );
4605	},
4606
4607	swap: function( newContent, onComplete ) {
4608
4609		if( newContent == this.newContent ) {
4610
4611			var s = this.settings;
4612			var oldContent = this.currentContent;
4613			var onOldContentOut;
4614			var onNewContentIn = function() {
4615
4616				if( s.endAnimateIn )
4617					s.onEndAnimateIn( newContent, onComplete );
4618
4619				if( onComplete )
4620					onComplete( newContent, oldContent );
4621			}
4622
4623			//- resize content if it can be resized
4624			newContent.resize && newContent.resize( s.width, s.height );
4625
4626			//- start animate in callback
4627			if( s.onStartAnimateIn )
4628				s.onStartAnimateIn( newContent, this.currentContent );
4629
4630			//- check for content on screen already
4631			if( this.currentContent ) {
4632
4633				onOldContentOut = function() {
4634
4635					if( s.onEndAnimateOut )
4636						s.onEndAnimateOut( newContent, oldContent );
4637
4638					if( oldContent.destroy )
4639						oldContent.destroy();
4640
4641					if( !s.overlap ) {
4642
4643						if( newContent.animateIn )
4644							newContent.animateIn( onNewContentIn );
4645						else 
4646							onNewContentIn();
4647					}
4648				};
4649
4650				if( s.onStartAnimateOut )
4651					s.onStartAnimateOut( newContent, oldContent );
4652
4653				if( oldContent.animateOut )
4654					oldContent.animateOut( onOldContentOut );
4655				else
4656					onOldContentOut();
4657
4658				if( s.overlap ) {
4659
4660					if( newContent.animateIn )
4661						newContent.animateIn( onNewContentIn );
4662					else
4663						onNewContentIn();
4664				}
4665			} else {
4666
4667				//- just bring in new content
4668				if( newContent.animateIn )
4669					newContent.animateIn( onNewContentIn );
4670				else 
4671					onNewContentIn();
4672			}
4673
4674			this.currentContent = newContent;
4675			this.newContent = null;
4676		}
4677	}
4678};
4679
4680module.exports = ViewManager;
4681},{}],25:[function(require,module,exports){
4682function mediator() {
4683
4684	if( !( this instanceof mediator ) ) {
4685
4686		var rVal = Object.create( mediator.prototype );
4687		mediator.apply( rVal, arguments );
4688		return rVal;
4689	}
4690
4691	this.items = arguments;
4692}
4693
4694mediator.prototype = {
4695
4696	init: function( data, onComplete ) {
4697
4698		var numInit = 0,
4699			numToInit = 0,
4700			numItem = this.items.length,
4701			onInit = function() {
4702
4703				if( ++numInit == numToInit )
4704					onComplete();
4705			};
4706
4707		// the following needs to be done in two for loops
4708		// because init may complete immediately
4709		// looks odd but it's needed
4710		for( var i = 0; i < numItem; i++ ) {
4711
4712			if( typeof this.items[ i ].init == 'function' )
4713				numToInit++;
4714		}
4715
4716		// now finally do the initialization
4717		for( var i = 0; i < numItem; i++ ) {
4718
4719			if( typeof this.items[ i ].init == 'function' )
4720				this.items[ i ].init( data, onInit );
4721		}
4722	},
4723
4724	resize: function( w, h ) {
4725
4726		for( var i = 0, len = this.items.length; i < len; i++ ) {
4727
4728			if( typeof this.items[ i ].resize == 'function' )
4729				this.items[ i ].resize( w, h );
4730		}
4731	},
4732
4733	aniIn: function( onComplete ) {
4734
4735		this.doAni( 'aniIn', onComplete );		
4736	},
4737
4738	aniOut: function( onComplete ) {
4739
4740		this.doAni( 'aniOut', onComplete );
4741	},
4742
4743	doAni: function( func, onComplete ) {
4744
4745		var numAni = numItem = 0,
4746			onAni = function() {
4747
4748				if( ++numAni == numItem )
4749					onComplete();
4750			};
4751
4752		// we need to do two loops here just in case onComplete gets called immediately
4753		for( var i = 0, len = this.items.length; i < len; i++ ) {
4754
4755			if( typeof this.items[ i ][ func ] == 'function' )
4756				numItem++;
4757		}
4758
4759		// now call the animate in functions
4760		for( var i = 0, len = this.items.length; i < len; i++ ) {
4761
4762			if( typeof this.items[ i ][ func ] == 'function' )
4763				this.items[ i ][ func ]( onAni );
4764		}
4765	},
4766
4767	destroy: function() {
4768
4769		for( var i = 0, len = this.items.length; i < len; i++ ) {
4770
4771			if( typeof this.items[ i ].destroy == 'function' )
4772				this.items[ i ].destroy();
4773		}
4774	}
4775};
4776
4777
4778module.exports = mediator;
4779},{}],26:[function(require,module,exports){
4780
4781
4782var VirtualScroll = function() {
4783
4784	var vs = {};
4785
4786	var numListeners, listeners = [], initialized = false;
4787
4788	var touchStartX, touchStartY;
4789
4790	// [ These settings can be customized with the options() function below ]
4791	// Mutiply the touch action by two making the scroll a bit faster than finger movement
4792	var touchMult = 2;
4793	// Firefox on Windows needs a boost, since scrolling is very slow
4794	var firefoxMult = 15;
4795	// How many pixels to move with each key press
4796	var keyStep = 500;
4797	// General multiplier for all mousehweel including FF
4798	var mouseMult = 1;
4799
4800	var bodyTouchAction;
4801
4802	var hasWheelEvent = 'onwheel' in document;
4803	var hasMouseWheelEvent = 'onmousewheel' in document;
4804	var hasTouch = 'ontouchstart' in document;
4805	var hasTouchWin = navigator.msMaxTouchPoints && navigator.msMaxTouchPoints > 1;
4806	var hasPointer = !!window.navigator.msPointerEnabled;
4807	var hasKeyDown = 'onkeydown' in document;
4808
4809	var isFirefox = navigator.userAgent.indexOf('Firefox') > -1;
4810
4811	var event = {
4812		y: 0,
4813		x: 0,
4814		deltaX: 0,
4815		deltaY: 0,
4816		originalEvent: null
4817	};
4818
4819	vs.on = function(f) {
4820		if(!initialized) initListeners(); 
4821		listeners.push(f);
4822		numListeners = listeners.length;
4823	}
4824
4825	vs.options = function(opt) {
4826		keyStep = opt.keyStep || 120;
4827		firefoxMult = opt.firefoxMult || 15;
4828		touchMult = opt.touchMult || 2;
4829		mouseMult = opt.mouseMult || 1;
4830	}
4831
4832	vs.off = function(f) {
4833		listeners.splice(f, 1);
4834		numListeners = listeners.length;
4835		if(numListeners <= 0) destroyListeners();
4836	}
4837
4838	var notify = function(e) {
4839		event.x += event.deltaX;
4840		event.y += event.deltaY;
4841		event.originalEvent = e;
4842
4843		for(var i = 0; i < numListeners; i++) {
4844			listeners[i](event);
4845		}
4846	}
4847
4848	var onWheel = function(e) {
4849		// In Chrome and in Firefox (at least the new one)
4850		event.deltaX = e.wheelDeltaX || e.deltaX * -1;
4851		event.deltaY = e.wheelDeltaY || e.deltaY * -1;
4852
4853		// for our purpose deltamode = 1 means user is on a wheel mouse, not touch pad 
4854		// real meaning: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent#Delta_modes
4855		if(isFirefox && e.deltaMode == 1) {
4856			event.deltaX *= firefoxMult;
4857			event.deltaY *= firefoxMult;
4858		} 
4859
4860		event.deltaX *= mouseMult;
4861		event.deltaY *= mouseMult;
4862
4863		notify(e);
4864	}
4865
4866	var onMouseWheel = function(e) {
4867		// In Safari, IE and in Chrome if 'wheel' isn't defined
4868		event.deltaX = (e.wheelDeltaX) ? e.wheelDeltaX : 0;
4869		event.deltaY = (e.wheelDeltaY) ? e.wheelDeltaY : e.wheelDelta;
4870
4871		notify(e);	
4872	}
4873
4874	var onTouchStart = function(e) {
4875		var t = (e.targetTouches) ? e.targetTouches[0] : e;
4876		touchStartX = t.pageX;	
4877		touchStartY = t.pageY;
4878	}
4879
4880	var onTouchMove = function(e) {
4881		// e.preventDefault(); // < This needs to be managed externally
4882		var t = (e.targetTouches) ? e.targetTouches[0] : e;
4883
4884		event.deltaX = (t.pageX - touchStartX) * touchMult;
4885		event.deltaY = (t.pageY - touchStartY) * touchMult;
4886		
4887		touchStartX = t.pageX;
4888		touchStartY = t.pageY;
4889
4890		notify(e);
4891	}
4892
4893	var onKeyDown = function(e) {
4894
4895		// 37 left arrow, 38 up arrow, 39 right arrow, 40 down arrow
4896		event.deltaX = event.deltaY = 0;
4897		switch(e.keyCode) {
4898			case 37:
4899				event.deltaX = -keyStep;
4900				break;
4901			case 39:
4902				event.deltaX = keyStep;
4903				break;
4904			case 38:
4905				event.deltaY = keyStep;
4906				break;
4907			case 40:
4908				event.deltaY = -keyStep;
4909				break;
4910		}
4911
4912		if( e.ctrlKey && e.keyCode == 40 ) {
4913			event.deltaY = -1000000;
4914		}
4915
4916		if( e.ctrlKey && e.keyCode == 38 ) {
4917			event.deltaY = 1000000;
4918		}
4919
4920		notify(e);
4921	}
4922
4923	var initListeners = function() {
4924		if(hasWheelEvent) document.addEventListener("wheel", onWheel);
4925		if(hasMouseWheelEvent) document.addEventListener("mousewheel", onMouseWheel);
4926
4927		if(hasTouch) {
4928			document.addEventListener("touchstart", onTouchStart);
4929			document.addEventListener("touchmove", onTouchMove);
4930		}
4931		
4932		if(hasPointer && hasTouchWin) {
4933			bodyTouchAction = document.body.style.msTouchAction;
4934			document.body.style.msTouchAction = "none";
4935			document.addEventListener("MSPointerDown", onTouchStart, true);
4936			document.addEventListener("MSPointerMove", onTouchMove, true);
4937		}
4938
4939		if(hasKeyDown) document.addEventListener("keydown", onKeyDown);
4940
4941		initialized = true;
4942	}
4943
4944	var destroyListeners = function() {
4945		if(hasWheelEvent) document.removeEventListener("wheel", onWheel);
4946		if(hasMouseWheelEvent) document.removeEventListener("mousewheel", onMouseWheel);
4947
4948		if(hasTouch) {
4949			document.removeEventListener("touchstart", onTouchStart);
4950			document.removeEventListener("touchmove", onTouchMove);
4951		}
4952		
4953		if(hasPointer && hasTouchWin) {
4954			document.body.style.msTouchAction = bodyTouchAction;
4955			document.removeEventListener("MSPointerDown", onTouchStart, true);
4956			document.removeEventListener("MSPointerMove", onTouchMove, true);
4957		}
4958
4959		if(hasKeyDown) document.removeEventListener("keydown", onKeyDown);
4960
4961		initialized = false;
4962	}
4963
4964	return vs;
4965};
4966
4967module.exports = VirtualScroll;
4968},{}],27:[function(require,module,exports){
4969module.exports = {
4970
4971	parent: function() {
4972
4973		//- if the current function calling is the constructor
4974		if( this.parent.caller._isConstructor ) {
4975
4976			var parentFunction = this.parent.caller._parentConstructor;
4977		} else {
4978
4979			if( this.parent.caller._name ) {
4980
4981				var callerName = this.parent.caller._name;
4982				var isGetter = this.parent.caller._owner._getters[ callerName ];
4983				var isSetter = this.parent.caller._owner._setters[ callerName ];
4984
4985				if( arguments.length == 1 && isSetter ) {
4986
4987					var parentFunction = Object.getPrototypeOf( this.parent.caller._owner )._setters[ callerName ];
4988
4989					if( parentFunction === undefined ) {
4990						throw 'No setter defined in parent';
4991					}
4992				} else if( arguments.length == 0 && isGetter ) {
4993
4994					var parentFunction = Object.getPrototypeOf( this.parent.caller._owner )._getters[ callerName ];
4995
4996					if( parentFunction === undefined ) {
4997						throw 'No getter defined in parent';
4998					}
4999				} else if( isSetter || isGetter ) {
5000
5001					throw 'Incorrect amount of arguments sent to getter or setter';
5002				} else {
5003
5004					var parentFunction = Object.getPrototypeOf( this.parent.caller._owner )[ callerName ];	
5005
5006    				if( parentFunction === undefined ) {
5007						throw 'No parent function defined for ' + callerName;
5008					}
5009				}
5010			} else {
5011
5012				throw 'Parent cannot be used in this context';
5013			}
5014		}
5015
5016		return parentFunction.apply( this, arguments );
5017	}
5018};
5019},{}],28:[function(require,module,exports){
5020var BaseClass = require( './BaseClass' );
5021
5022var Class = function( descriptor ) {
5023
5024	var rval = undefined;
5025
5026	if ( descriptor === undefined ) {
5027
5028		descriptor = {};
5029	}
5030
5031	if( descriptor.initialize ) {
5032
5033		rval = descriptor.initialize;
5034		delete descriptor.initialize;
5035	} else {
5036
5037		rval = function() { 
5038
5039			Array.prototype.splice.apply( arguments, [ 0, 0, this ] );
5040
5041			Class.parent.apply( undefined, arguments );
5042		};
5043	}
5044
5045	if( descriptor.Extends !== undefined ) {
5046
5047		descriptor.Extends();
5048		descriptor.Extends._isConstructor = true;
5049
5050		rval.prototype = Object.create( descriptor.Extends.prototype );
5051		
5052		// this will be used to call the parent constructor
5053		rval._parentConstructor = descriptor.Extends;
5054		delete descriptor.Extends;
5055	} else {
5056
5057		rval.prototype = Object.create( BaseClass );
5058		rval._parentConstructor = function() {};
5059	}
5060
5061	rval.prototype._getters = {};
5062	rval.prototype._setters = {};
5063
5064	for( var i in descriptor ) {
5065		if( typeof descriptor[ i ] == 'function' ) {
5066			descriptor[ i ]._name = i;
5067			descriptor[ i ]._owner = rval.prototype;
5068
5069			rval.prototype[ i ] = descriptor[ i ];
5070		} else if( descriptor[ i ] && typeof descriptor[ i ] == 'object' && ( descriptor[ i ].get || descriptor[ i ].set ) ) {
5071			Object.defineProperty( rval.prototype, i , descriptor[ i ] );
5072
5073			if( descriptor[ i ].get ) {
5074				rval.prototype._getters[ i ] = descriptor[ i ].get;
5075				descriptor[ i ].get._name = i;
5076				descriptor[ i ].get._owner = rval.prototype;
5077			}
5078
5079			if( descriptor[ i ].set ) {
5080				rval.prototype._setters[ i ] = descriptor[ i ].set;
5081				descriptor[ i ].set._name = i;
5082				descriptor[ i ].set._owner = rval.prototype;	
5083			}
5084		} else {
5085			rval.prototype[ i ] = descriptor[ i ];
5086		}
5087	}
5088
5089	// this will be used to check if the caller function is the consructor
5090	rval._isConstructor = true;
5091
5092	// now we'll check interfaces
5093	for( var i = 1; i < arguments.length; i++ ) {
5094		arguments[ i ].compare( rval );
5095	}
5096
5097	return rval;
5098};	
5099
5100Class.parent = function( scope ) {
5101
5102	var caller = Class.parent.caller;
5103
5104	arguments = Array.prototype.slice.apply( arguments, [ 1 ] )
5105
5106	// if the current function calling is the constructor
5107	if( caller._isConstructor ) {
5108		var parentFunction = caller._parentConstructor;
5109	} else {
5110		if( caller._name ) {
5111			var callerName = caller._name;
5112			var isGetter = caller._owner._getters[ callerName ];
5113			var isSetter = caller._owner._setters[ callerName ];
5114
5115			if( arguments.length == 1 && isSetter ) {
5116				var parentFunction = Object.getPrototypeOf( caller._owner )._setters[ callerName ];
5117
5118				if( parentFunction === undefined ) {
5119					throw 'No setter defined in parent';
5120				}
5121			} else if( arguments.length == 0 && isGetter ) {
5122				var parentFunction = Object.getPrototypeOf( caller._owner )._getters[ callerName ];
5123
5124				if( parentFunction === undefined ) {
5125					throw 'No getter defined in parent';
5126				}
5127			} else if( isSetter || isGetter ) {
5128				throw 'Incorrect amount of arguments sent to getter or setter';
5129			} else {
5130				var parentFunction = Object.getPrototypeOf( caller._owner )[ callerName ];	
5131
5132				if( parentFunction === undefined ) {
5133					throw 'No parent function defined for ' + callerName;
5134				}
5135			}
5136		} else {
5137			throw 'You cannot call parent here';
5138		}
5139	}
5140
5141	return parentFunction.apply( scope, arguments );
5142};
5143
5144module.exports = Class;
5145},{"./BaseClass":27}],29:[function(require,module,exports){
5146
5147
5148var Class = require('./../components/oop/Class');
5149var View = require('./../components/View');
5150var Velocity = require('velocity-animate');
5151var $ = require('./../components/DOM');
5152var SmoothScroll = require('./../components/SmoothScroll');
5153
5154var _ = require('underscore');
5155var _data = require('./../Data').blog;
5156
5157var headerDark = false;
5158
5159var BlogView = new Class({
5160
5161	name: "blog-post-view",
5162	Extends: View,
5163	template: "<div class=\"page-title\">\n\t<h1>News &amp; Events</h1>\n</div>\n\n<div class=\"post\">\n\n\t<div class=\"inner\">\n\t\t\n\t\t<div class=\"social\">\n\t\t\t<ul>\n\t\t\t\t<li>\n\t\t\t\t\t<a href=\"http://www.facebook.com/sharer.php?s=100&p[url]=http://www.thestlbrowns.com/%23/news-and-events/{{ slug }}&p[images][0]=/og-image.jpg&p[title]=The St. Louis Browns Historical Society&p[summary]=The St. Louis Browns Historical Society and Fan Club is dedicated to preserving every stat and story, so the legend of baseball's most colorful underdogs can endure forever.\" target=\"_blank\" class=\"facebook\">F</a>\n\t\t\t\t</li>\n\t\t\t\t<li>\n\t\t\t\t\t<a href=\"https://twitter.com/intent/tweet?text=The St. Louis Browns Historical Society and Fan Club is dedicated to preserving every stat and story, so the legend of baseball's most colorful underdogs can endure forever.&url=http://www.thestlbrowns.com/%23/news-and-events/{{ slug }}\" target=\"_blank\" class=\"twitter\">T</a>\n\t\t\t\t</li>\n\t\t\t\t<li>\n\t\t\t\t\t<a href=\"mailto:?body=Here is a link to an article I found on the St. Louis Browns Historical Society website: http://www.thestlbrowns.com/%23/news-and-events/{{ slug }}&amp;subject=An article from the St. Louis Browns Historical Society\" class=\"email\">M</a>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<div class=\"post-body\">\n\t\t\t\n\t\t\t<p class=\"date\">{{ date }}</p>\n\t\t\t<h2>{{ title }}</h2>\n\t\t\t<p class=\"lead\">{{{ excerpt }}}</p>\n\n\t\t\t{{ #images.article }}\n\t\t\t<div class=\"post-image\">\n\t\t\t\t<img src=\"{{ . }}\" alt=\"\" />\n\t\t\t</div>\n\t\t\t{{ /images.article }}\n\n\t\t\t{{{ body }}}\n\t\n\t\t\t<hr />\n\t\t\t<p>\n\t\t\t\t<a href=\"#/news-and-events\">&larr; Back to all posts</a>\n\t\t\t</p>\n\t\t\t\n\t\t</div>\n\n\t</div>\n\n</div>",
5164
5165	init: function( routeData, onComplete ) {
5166
5167		var _this = this;
5168
5169		this.renderer = new SmoothScroll( this.onRender.bind(this) );
5170
5171		var postId = routeData.params.id;
5172
5173		var postData = _.findWhere(_data.posts, { slug: postId });
5174
5175		this.render(postData, Stage);
5176		$.addClass('page', this.div);
5177
5178		this.content = $.select('.post', this.div);
5179		this.title = $.select('.page-title h1', this.div);
5180
5181		var header = $.select('.page-title', this.div);
5182		this.headerHeight = header[ 0 ].scrollHeight;
5183
5184		onComplete();
5185
5186		setTimeout(function() {
5187
5188			_this.resize();
5189		}, 100);
5190
5191		this.addListeners();
5192	},
5193
5194	addListeners: function() {
5195		
5196		$.on(this.div, 'click', function(e) {
5197
5198			if( $.hasClass(e.target, 'twitter') || $.hasClass(e.target, 'facebook') ) {
5199
5200				e.preventDefault();
5201
5202				var href = e.target.getAttribute('href');
5203
5204				window.open(href, null, 'height=420, width=550');
5205			}
5206		});
5207	},
5208
5209	animateOut: function( onComplete ) {
5210
5211		Velocity(this.div, {
5212			opacity: [ 0, 1 ]
5213		}, {
5214			duration: 1000,
5215			complete: onComplete
5216		});
5217
5218		this.renderer.stopRender();
5219	},
5220
5221	animateIn: function( onComplete ) {
5222
5223		this.renderer.startRender();
5224
5225		Velocity(this.div, {
5226			opacity: [ 1, 0 ]
5227		}, {
5228			duration: 1000,
5229			complete: onComplete,
5230			easing: 'linear'
5231		});
5232	},
5233
5234	onRender: function( scr ) {
5235
5236		var op = 1 - ((scr / 5) / -100);
5237
5238		$.transform(this.content, {
5239			y: scr
5240		});
5241
5242		$.transform(this.title, {
5243			y: (scr * 0.15)
5244		}).css(this.title, {
5245			opacity: op
5246		});
5247
5248		if( scr < -this.headerHeight && !headerDark ) {
5249
5250			$.addClass('dark', this.navController);
5251			headerDark = true;
5252		} else if( scr > -this.headerHeight && headerDark ) {
5253
5254			$.removeClass(this.navController, 'dark');
5255			headerDark = false;
5256		}
5257	},
5258
5259	resize: function( w, h ) {
5260
5261		var max = Math.max(0, (this.div.scrollHeight - window.innerHeight));
5262		this.renderer.setLimits((max * -1), 0);
5263
5264		var header = $.select('.page-title', this.div);
5265		this.headerHeight = header[ 0 ].scrollHeight;
5266	}
5267});
5268
5269module.exports = BlogView;
5270},{"./../Data":2,"./../components/DOM":6,"./../components/SmoothScroll":19,"./../components/View":23,"./../components/oop/Class":28,"underscore":53,"velocity-animate":54}],30:[function(require,module,exports){
5271
5272
5273var Class = require('./../components/oop/Class');
5274var View = require('./../components/View');
5275var Velocity = require('velocity-animate');
5276var $ = require('./../components/DOM');
5277
5278var ContactView = new Class({
5279
5280	name: "contact-view",
5281	Extends: View,
5282	template: "<div class=\"page-title\">\n\t<h1>Contact</h1>\n</div>\n\n<div class=\"content\">\n\t\n\t<div class=\"inner\">\n\t\n\t\t<div class=\"grid grid-padded\">\n\t\t\t\n\t\t\t<div>\n\t\t\t\t\n\t\t\t\t<h2>Contact The Society</h2>\n\t\t\t\t<p>If you want to learn more about the St. Louis Browns, the Historical Society, membership, upcoming events, or any other related topic, please fill out the form below. Someone will get back to you shortly.</p>\n\n\t\t\t</div>\n\n\t\t\t<div>\n\n\t\t\t\t<form id=\"contact\" novalidate>\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"name\" name=\"name\" type=\"text\" placeholder=\"Your Name\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"email\" name=\"email\" type=\"email\" placeholder=\"Email Address\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"phone\" name=\"phone\" type=\"text\" placeholder=\"Phone Number\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<textarea id=\"comment\" name=\"comment\" placeholder=\"Question/Comment\"></textarea>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group error\">\n\t\t\t\t\t\t<p>All fields are required.</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<button type=\"submit\" class=\"submit\">Submit</button>\n\t\t\t\t</form>\n\n\t\t\t</div>\n\n\t\t</div>\n\n\t</div>\n\n</div>",
5283
5284	init: function( data, onComplete ) {
5285
5286		var nav = $.select('.nav-controller');
5287		$.addClass('dark', nav);
5288
5289		this.render(data, Stage);
5290		$.addClass('page', this.div);
5291
5292		onComplete();
5293	},
5294
5295	animateOut: function( onComplete ) {
5296
5297		Velocity(this.div, {
5298			opacity: [ 0, 1 ]
5299		}, {
5300			duration: 1000,
5301			complete: onComplete
5302		});
5303	},
5304
5305	animateIn: function( onComplete ) {
5306
5307		Velocity(this.div, {
5308			opacity: [ 1, 0 ]
5309		}, {
5310			duration: 1000,
5311			complete: onComplete
5312		});
5313	},
5314
5315	resize: function( w, h ) {
5316
5317		// console.log(w, h);
5318	}
5319});
5320
5321module.exports = ContactView;
5322},{"./../components/DOM":6,"./../components/View":23,"./../components/oop/Class":28,"velocity-animate":54}],31:[function(require,module,exports){
5323
5324
5325var Class = require('./../components/oop/Class');
5326var View = require('./../components/View');
5327var Velocity = require('velocity-animate');
5328var $ = require('./../components/DOM');
5329
5330var Data = require('./../Data');
5331var Config = require('./../Config');
5332var Serialize = require('./../components/FormSerializer');
5333var Loader = require('./../components/Loader');
5334var Util = require('./../components/Utils');
5335
5336var SmoothScroll = require('./../components/SmoothScroll');
5337
5338var headerDark = false, headerHeight;
5339var footer = "<footer>\n\t\n\t<div class=\"inner\">\n\t\t\n\t\t<div class=\"grid grid-middle\">\n\n\t\t\t<div class=\"logo\">\n\t\t\t\t<img src=\"/images/img-footer-logo.png\" alt=\"\" />\n\t\t\t</div>\n\t\t\t\n\t\t\t<div>\n\t\t\t\t<a href=\"#/\">Home</a>\n\t\t\t</div>\n\n\t\t\t<div>\n\t\t\t\t<a href=\"#/history\">history</a>\n\t\t\t</div>\n\n\t\t\t<div>\n\t\t\t\t<a href=\"#/players\">Players</a>\n\t\t\t</div>\n\n\t\t\t<div>\n\t\t\t\t<a href=\"#/about\">About</a>\n\t\t\t</div>\n\n\t\t\t<div>\n\t\t\t\t<a href=\"#/membership\">Membership</a>\n\t\t\t</div>\n\n\t\t\t<div>\n\t\t\t\t<a href=\"#/news-and-events\">News &amp; Events</a>\n\t\t\t</div>\n\n\t\t\t<div>\n\t\t\t\t<a href=\"#/contact\">Contact</a>\n\t\t\t</div>\n\n\t\t</div>\n\n\t</div>\n\n</footer>";
5340
5341var testEmail = function(email) {
5342
5343	var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
5344	return re.test(email);
5345}
5346
5347var isVisible = function(el) {
5348
5349    var rect = el.getBoundingClientRect();
5350
5351    return (
5352        rect.top >= -rect.height &&
5353        rect.bottom >= 0
5354    );
5355};
5356
5357var GenericView = new Class({
5358
5359	name: "generic-view",
5360	Extends: View,
5361	templates: {
5362
5363		"about": "<div class=\"page-title\">\n\t<h1>About The Society</h1>\n</div>\n\n<div class=\"content\">\n\n\t<div class=\"top\">\n\n\t\t<div class=\"intro\">\n\n\t\t\t<h5>Overview</h5>\n\t\t\t<p>41 losing seasons in 52 years. A whiff of a World Series. Misfits, a midget, and money problems. The Browns are baseball’s losingest and least remembered team. But beneath the tarnish is true baseball gold. Heroes of the greatest generation. Moments of grit, guts and glory. A roller coaster of ruin and redemption. The St. Louis Browns Historical Society and Fan Club is dedicated to preserving every stat and story, so the legend of baseball’s most colorful underdogs can endure forever.</p>\n\n\t\t</div>\n\n\t\t<div class=\"board\">\n\n\t\t\t<h2>Board Members</h2>\n\n\t\t\t<div class=\"grid\">\n\n\t\t\t\t<div>\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/about-photo-ed-wheatley.png\" alt=\"\" />\n\t\t\t\t\t<h6>Ed Wheatley, President</h6>\n\t\t\t\t\t<p>Ed grew up in and around the world of baseball, from his youth when his dad played professionally through his own baseball activities as he continues to play senior league games across the country.  After a 36 year business career, Ed sought to make baseball his full time passion by working to preserve the legacy of this transplanted American League team co-authoring the award winning The St. Louis Browns: The Story of A Beloved Team and authoring Incredible Cardinals and Baseball in St. Louis – Little Leagues to Major Leagues.  These works led to two films he helped produce shown on the PBS network in 2018 and 19 that received an EMMY nomination and selection into the National Baseball Hall of Fame’s Annual Film Series in Cooperstown in 2018 and 19 where Ed had the honor of introducing the films and speaking on the Browns.</p>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/about-photo-emmett.png\" alt=\"\" />\n\t\t\t\t\t<h6>Emmett McAuliffe</h6>\n\t\t\t\t\t<p>Emmett is an attorney and partner with Riezman Berger, P.C., a law firm in Clayton, MO. His practice focuses on intellectual property, offering special services to the music, film, art and fashion communities. From 2008 to 2011, he served as a gubernatorial appointment to the Missouri Arts Council. A lifelong St. Louisan, Emmett became a Browns fan as a five-year-old in the mid-1960s when an older boy showed him a Browns baseball card.</p>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/about-photo-vicki-martin.png\" alt=\"\" />\n\t\t\t\t\t<h6>Vicki Martin</h6>\n\t\t\t\t\t<p>Vicki Martin was a supervisor at the St. Louis Family Court – Juvenile Division for 38 years. As a director on the Browns Historical Society board, she is responsible for marketing the fan club services and products. Ms. Martin grew up in a baseball family and is the niece of former Browns player, Babe Martin. Babe played for six years, splitting time between the Browns and the Boston Red Sox.</p>\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t\t<div class=\"grid\">\n\n\t\t\t\t<div>\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/about-photo-lewis-levey.png\" alt=\"\" />\n\t\t\t\t\t<h6>Lewis Levey</h6>\n\t\t\t\t\t<p>For most of his business career, Lewis A. Levey was a real estate developer focused on office buildings and apartment communities in many different states.  Currently, he serves as Chairman of Enhanced Value Strategies, Inc., a company providing strategic real estate consulting and advisory services to both private and institutional investors. Mr. Levey serves on the Board of Directors of two public companies, as well as several not-for-profit organizations in the St. Louis area, including Washington University Olin School of Business N
5363ational Council and Alumni Board, the St. Louis Sports Commission, and others.  A long-time sports enthusiast, he still has the baseball he caught at a Browns game in 1951.</p>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/about-photo-bill-borst.png\" alt=\"\" />\n\t\t\t\t\t<h6>Bill Borst</h6>\n\t\t\t\t\t<p>A native New Yorker, Bill founded the St. Louis Browns Historical Society in 1984. He was the club&rsquo;s first president and launched many of its publications. Known as the &ldquo;Baseball Professor,&rdquo; Bill taught the first accredited baseball history course in the Midwest at Maryville College in 1973. He has previously hosted baseball call-in shows on WGNU radio and has written several non-fiction novels, including The Scorpion and the Frog: A Natural Conspiracy.</p>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/about-photo-stl-browns.png\" alt=\"\" />\n\t\t\t\t\t<h6></h6>\n\t\t\t\t\t<p></p>\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t</div>\n\n\t\t<div class=\"hof grid grid-padded grid-middle\">\n\n\t\t\t<div class=\"image\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/about-stlsports-hof.png\" alt=\"\" />\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h2>St. Louis Sports Hall of Fame</h2>\n\t\t\t\t<p>The St. Louis Browns Fan Club is honored to be a member of the St. Louis Sports Hall of Fame, which preserves the memories of the greatest moments and events in St. Louis sports history. Our extensive exhibit includes Browns uniforms, photos of games and players, pennants, and other memorabilia.</p>\n\t\t\t</div>\n\n\t\t</div><div class=\"hof grid grid-padded grid-middle\">\n\n\t\t\t<div class=\"image\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/amateur-baseball.png\" alt=\"\" />\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<h2>Greater St. Louis Amateur Baseball HOF</h2>\n\t\t\t\t<p>The St. Louis Browns Historical Society & Fan Club is a proud partner and supporter of the Greater St. Louis Amateur Baseball Hall of Fame and recipient of the HOF’s first Legacy Award Winner in 2018.</p>\n\t\t\t</div>\n\n\t\t</div>\n\n\t\t<img src=\"{{ Config.cdn }}images/bg/bg-about.png\" alt=\"\" class=\"bg\" />\n\n\t</div>\n\n\t<div class=\"form dark\">\n\n\t\t<div class=\"inner grid grid-padded grid-middle\">\n\t\t\t<div>\n\t\t\t\t<h2>Become a member</h2>\n\t\t\t\t<p>By joining, you&rsquo;ll help support our organization&rsquo;s efforts to preserve the history of the St. Louis Browns. Fill out the form to the right, and someone from the Browns Historical Society will contact you to complete your membership.</p>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<form id=\"contact\" novalidate>\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"name\" name=\"name\" type=\"text\" placeholder=\"Your Name\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"email\" name=\"email\" type=\"email\" placeholder=\"Email Address\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"phone\" name=\"phone\" type=\"text\" placeholder=\"Phone Number\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<textarea id=\"comment\" name=\"comment\" placeholder=\"Question/Comment\"></textarea>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<button type=\"submit\" class=\"submit\">Submit</button>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\n\t</div>\n\n\t<div class=\"next-section\">\n\t\t<h2>\n\t\t\t<a href=\"#/history\">The History of the Browns &rarr;</a>\n\t\t</h2>\n\t</div>\n\n</div>",
5364		"membership": "<div class=\"page-title\">\n\t<h1>Membership</h1>\n</div>\n\n<div class=\"content\">\n\n\t<div class=\"top\">\n\t\n\t\t<div class=\"intro\">\n\n\t\t\t<h5>Membership Pledge</h5>\n\t\t\t<p>As a member of the St. Louis Browns Fan Club, I pledge to protect, preserve and promote the St. Louis Browns. I accept the duty to defend the honor of the Browns wherever it may be maligned and tell Browns stories wherever and whenever I can. I will exercise careful stewardship over Browns artifacts and memorabilia. I gladly accept the duty of preventing our Browns from ever becoming forgotten by future generations of baseball fans. </p>\n\n\t\t</div>\n\t\t\n\t\t<div class=\"membership-levels\">\n\n\t\t\t<h2>Membership Levels</h2>\n\t\t\t<div class=\"grid grid-middle\">\n\t\t\t\t<div class=\"icon\">\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/member-level-bleed-brown.png\" alt=\"Bleed Brown\" />\n\t\t\t\t</div>\n\t\t\t\t<div><b>$100 per year*</b> // Includes membership ID card; an invitation to all Browns Historical Society activities, including the players dinner before the annual luncheon (extra fee); a subscription to Pop Flies, the St. Louis Browns magazine; a special issue of Pop Flies with highlights of the 70th anniversary of the ’44 World Series; a DVD of the 1944 World Series; your name listed on the donor honor roll; a Browns/Cardinals 70th anniversary World Series pennant.</div>\n\t\t\t</div>\n\t\t\t<div class=\"grid grid-middle\">\n\t\t\t\t<div class=\"icon\">\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/member-level-gold.png\" alt=\"Gold\" />\n\t\t\t\t</div>\n\t\t\t\t<div><b>$60 per year*</b> // Includes membership ID card; a subscription to Pop Flies, the St. Louis Browns magazine; a special issue of Pop Flies with highlights of the 70th anniversary of the ’44 World Series; historical search help; a Browns lapel pin; DVD highlights of the last member luncheon; your name listed on the donor honor roll.</div>\n\t\t\t</div>\n\t\t\t<div class=\"grid grid-middle\">\n\t\t\t\t<div class=\"icon\">\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/member-level-silver.png\" alt=\"Silver\" />\n\t\t\t\t</div>\n\t\t\t\t<div><b>$30 per year*</b> // Includes membership ID card; a subscription to Pop Flies, the St. Louis Browns magazine; historical search help; an invitation to Browns Historical Society activities (extra fees may apply).</
5364div>\n\t\t\t</div>\n\t\t\t<div class=\"legal\">*Membership fees are tax deductible. The St. Louis Browns Historical Society and Fan Club is a 501c3 organization.</div>\n\n\t\t</div>\n\n\t\t<img src=\"{{ Config.cdn }}images/bg/bg-membership.png\" alt=\"\" class=\"bg\" />\n\n\t</div>\n\t\t\n\t<div class=\"form dark\">\n\n\t\t<div class=\"inner grid grid-padded grid-middle\">\n\t\t\t<div>\n\t\t\t\t<h2>Become a member</h2>\n\t\t\t\t<p>If you want to learn more about the St. Louis Browns, the Historical Society, membership, upcoming events, or any other related topic, please fill out the form below. Someone will get back to you shortly to discuss payment options.</p>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<form id=\"contact\" novalidate>\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"name\" name=\"name\" type=\"text\" placeholder=\"Your Name\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"email\" name=\"email\" type=\"email\" placeholder=\"Email Address\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"phone\" name=\"phone\" type=\"text\" placeholder=\"Phone Number\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group select\" data-required>\n\t\t\t\t\t\t<select name=\"memberlevel\" id=\"membership-level\">\n\t\t\t\t\t\t\t<option value=\"\">Select membership level...</option>\n\t\t\t\t\t\t\t<option value=\"silver\">Silver</option>\n\t\t\t\t\t\t\t<option value=\"gold\">Gold</option>\n\t\t\t\t\t\t\t<option value=\"bleed-brown\">Bleed Brown</option>\n\t\t\t\t\t\t</select>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group error\">\n\t\t\t\t\t\t<p>All fields are required.</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<button type=\"submit\" class=\"submit\">Submit Membership Request</button>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\n\t</div>\n\n\t<div class=\"next-section\">\n\t\t<h2>\n\t\t\t<a href=\"#/players\">Browns Players &rarr;</a>\n\t\t</h2>\n\t</div>\n\n</div>",
5365		"news-and-events": "<div class=\"page-title\">\n\t<h1>News &amp; Events</h1>\n</div>\n\n<div class=\"content\">\n\t\n\t<div class=\"posts\">\n\t\t{{ #blog.posts }}\n\n\t\t\t<div class=\"post grid grid-middle\">\n\t\t\t\t\n\t\t\t\t{{ #images.news }}\n\t\t\t\t\t<div class=\"image\" style=\"background-image: url( '{{ . }}' );\"></div>\n\t\t\t\t{{ /images.news }}\n\t\t\t\t<article>\n\t\t\t\t\t<p class=\"date\">{{ date }}</p>\n\t\t\t\t\t<h2>{{ #trimmedTitle }}{{ title }}{{ /trimmedTitle }}</h2>\n\t\t\t\t\t<a href=\"#/news-and-events/{{ slug }}\" class=\"btn\">Read More</a>\n\t\t\t\t</article>\n\n\t\t\t\t<div class=\"social\">\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<a href=\"http://www.facebook.com/sharer.php?s=100&p[url]=http://www.thestlbrowns.com/%23/news-and-events/{{ slug }}&p[images][0]=/og-image.jpg&p[title]=The St. Louis Browns Historical Society&p[summary]={{ #trimmedTitle }}{{ title }}{{ /trimmedTitle }}\" target=\"_blank\" class=\"facebook\">F</a>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<a href=\"https://twitter.com/intent/tweet?text={{ #trimmedTitle }}{{ title }}{{ /trimmedTitle }}&url=http://www.thestlbrowns.com/%23/news-and-events/{{ slug }}\" target=\"_blank\" class=\"twitter\">T</a>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<a href=\"mailto:?body=Here is a link to an article I found on the St. Louis Browns Historical Society website: http://www.thestlbrowns.com/%23/news-and-events/{{ slug }}&amp;subject=An article from the St. Louis Browns Historical Society\" class=\"email\">M</a>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t{{ /blog.posts }}\n\t</div>\n\n</div>\n\n",
5366		"contact": "<div class=\"page-title\">\n\t<h1>Contact</h1>\n</div>\n\n<div class=\"content\">\n\t\n\t<div class=\"inner\">\n\t\n\t\t<div class=\"grid grid-padded\">\n\t\t\t\n\t\t\t<div>\n\t\t\t\t\n\t\t\t\t<h2>Contact The Society</h2>\n\t\t\t\t<p>If you want to learn more about the St. Louis Browns, the Historical Society, membership, upcoming events, or any other related topic, please fill out the form below. Someone will get back to you shortly.</p>\n\n\t\t\t</div>\n\n\t\t\t<div>\n\n\t\t\t\t<form id=\"contact\" novalidate>\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"name\" name=\"name\" type=\"text\" placeholder=\"Your Name\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"email\" name=\"email\" type=\"email\" placeholder=\"Email Address\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<input id=\"phone\" name=\"phone\" type=\"text\" placeholder=\"Phone Number\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group\" data-required>\n\t\t\t\t\t\t<textarea id=\"comment\" name=\"comment\" placeholder=\"Question/Comment\"></textarea>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"form-group error\">\n\t\t\t\t\t\t<p>All fields are required.</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<button type=\"submit\" class=\"submit\">Submit</button>\n\t\t\t\t</form>\n\n\t\t\t</div>\n\n\t\t</div>\n\n\t</div>\n\n</div>"
5367
5368	},
5369
5370	init: function( data, onComplete ) {
5371
5372		var _this = this;
5373		var r = data.route.split('/')[ 1 ]
5374		this.template = this.templates[ r ];
5375		Data.Config = Config;
5376
5377		Data.trimmedTitle = function() {
5378
5379			return function (text, render) {
5380
5381				var t = render(text);
5382
5383				if( t.length > 70 ) {
5384					var tr = Util.truncate(t, 70) + '...';
5385					return tr;
5386				} else {
5387					return t;
5388				}
5389			}
5390		};
5391
5392		var nav = this.navController = $.select('.nav-controller');
5393		$.removeClass(nav, 'dark');
5394
5395		this.render(Data, Stage);
5396
5397		$.addClass('page ' + r + '-view', this.div);
5398
5399		//- set up smooth scroll renderer
5400		this.renderer = new SmoothScroll( this.onRender.bind(this) );
5401
5402		this.content = $.select('.content', this.div);
5403		this.title = $.select('.page-title h1', this.div);
5404		this.backgroundImage = $.select('.bg', Stage);
5405
5406		var header = $.select('.page-title', this.div);
5407		headerHeight = header[ 0 ].scrollHeight;
5408
5409		// attach footer to content div
5410		this.content[ 0 ].innerHTML += footer;
5411
5412		this.bindUI();
5413
5414		setTimeout(onComplete, 100);
5415	},
5416
5417	bindUI: function() {
5418
5419		var form = this.form = $.select('form', this.div)[ 0 ];
5420
5421		if( form ) $.on(form, 'submit', this.formSubmit);
5422
5423		$.on(this.div, 'click', function(e) {
5424
5425			if( $.hasClass(e.target, 'twitter') || $.hasClass(e.target, 'facebook') ) {
5426
5427				e.preventDefault();
5428
5429				var href = e.target.getAttribute('href');
5430
5431				window.open(href, null, 'height=420, width=550');
5432			}
5433		});
5434	},
5435
5436	formSubmit: function( e ) {
5437
5438		var form = this.form;
5439
5440		var error = $.select('.error', form)[ 0 ];
5441		var button = $.select('.submit', form)[ 0 ];
5442
5443		e.preventDefault();
5444
5445		$.css(error, { display: 'none' });
5446		button.disabled = true;
5447
5448		var valid = true;
5449		var required = $.select('[data-required]', form);
5450
5451		for( var i = 0; i < required.length; i ++ ) {
5452
5453			var input = $.select('input, textarea, select', required[ i ])[ 0 ];
5454			var type = input.getAttribute('type') || 'text';
5455			var val = input.value;
5456
5457			if( type == 'text' && val == '' ) valid = false;
5458			if( type == 'email' && !testEmail(val) ) valid = false;
5459		}
5460
5461		if( valid ) {
5462
5463			var data = Serialize(e.target);
5464			var form = $.select('#contact')[ 0 ];
5465
5466			$.css(form, {
5467				height: form.scrollHeight
5468			});
5469
5470			Loader.post('/api/contact?', data, function( res ) {
5471
5472				form.innerHTML = '<p>' + res.message + '</p>';
5473			});
5474		} else {
5475
5476			$.css(error, { display: 'block' });
5477			button.disabled = false;
5478		}
5479	},
5480
5481	animateOut: function( onComplete ) {
5482
5483		Velocity(this.div, {
5484			opacity: [ 0, 1 ]
5485		}, {
5486			duration: 1000,
5487			complete: onComplete
5488		});
5489
5490		this.renderer.stopRender();
5491	},
5492
5493	animateIn: function( onComplete ) {
5494
5495		this.renderer.startRender();
5496
5497		Velocity(this.div, {
5498			opacity: [ 1, 0 ]
5499		}, {
5500			duration: 1000,
5501			complete: onComplete,
5502			easing: 'linear'
5503		});
5504
5505		this.backgroundImage = $.select('.bg', Stage);
5506		this.sections = $.select('.top', this.div);
5507		this.resize();
5508	},
5509
5510	onRender: function( scr ) {
5511
5512		var op = 1 - ((scr / 2) / -100);
5513
5514		$.transform(this.content, {
5515			y: scr
5516		});
5517
5518		$.transform(this.backgroundImage, {
5519			y: (scr * -0.075)
5520		});
5521
5522		$.transform(this.title, {
5523			y: (scr * 0.15)
5524		}).css(this.title, {
5525			opacity: op
5526		});
5527
5528		for( var i = 0; i < this.sections.length; i ++ ) {
5529
5530			var visible = isVisible(this.sections[ i ]);
5531
5532			if( scr < -headerHeight ) {
5533
5534				if( visible && !headerDark ) {
5535
5536					$.addClass('dark', this.navController);
5537					headerDark = true;
5538				} else if( !visible && headerDark ) {
5539
5540					$.removeClass(this.navController, 'dark');
5541					headerDark = false;
5542				}
5543			} else {
5544
5545				if( headerDark ) {
5546
5547					$.removeClass(this.navController, 'dark');
5548					headerDark = false;
5549				}
5550			}
5551		}
5552	},
5553
5554	resize: function( w, h ) {
5555
5556		var max = Math.max(0, (this.div.scrollHeight - window.innerHeight));
5557		this.renderer.setLimits((max * -1), 0);
5558
5559		var header = $.select('.page-title', this.div);
5560		headerHeight = header[ 0 ].scrollHeight;
5561	}
5562});
5563
5564module.exports = GenericView;
5565},{"./../Config":1,"./../Data":2,"./../components/DOM":6,"./../components/FormSerializer":9,"./../components/Loader":12,"./../components/SmoothScroll":19,"./../components/Utils":22,"./../components/View":23,"./../components/oop/Class":28,"velocity-animate":54}],32:[function(require,module,exports){
5566
5567
5568
5569var Class = require('./../components/oop/Class');
5570var View = require('./../components/View');
5571var Velocity = require('velocity-animate');
5572var _ = require('underscore');
5573
5574var Hero = require('./../components/HistoryHero');
5575var HistoryTimeline = require('./../components/HistoryTimeline');
5576
5577var $ = require('./../components/DOM');
5578var _data = require('./../Data').historySection;
5579var Config = require('./../Config');
5580var Util = require('./../components/Utils');
5581var Device = require('./../components/Device');
5582
5583var Overlay = require('./../components/Overlay');
5584var Carousel = require('./../components/Carousel');
5585
5586var SmoothScroll = require('./../components/SmoothScroll');
5587var VirtualScroll = require('./../components/VirtualScroll')();
5588
5589var threshold = 0.8;
5590
5591var isVisible = function(el) {
5592
5593    var rect = el.getBoundingClientRect();
5594
5595    return (
5596        rect.top <= (window.innerHeight * threshold) &&
5597        rect.bottom >= (window.innerHeight * threshold) &&
5598        rect.left >= 0 &&
5599        rect.right <= window.innerWidth
5600    );
5601};
5602
5603var HistoryView = new Class({
5604
5605	name: "history-section-view",
5606	Extends: View,
5607	overlay: new Overlay(),
5608	
5609	templates: {
5610		"the-early-years": "<div class=\"border border-top\"></div>\n<div class=\"border border-right\"></div>\n<div class=\"border border-bottom\"></div>\n<div class=\"border border-left\"></div>\n\n<div class=\"inner\">\n\n\t<div class=\"timeline-bar\"></div>\n\n\t<section class=\"browns-town\">\n\n\t\t<div class=\"content\" data-theme=\"light\" data-year=\"1902\" data-section-title=\"Inaugural Season\">\n\t\t\t<div class=\"grid section-1 contain grid-middle\">\n\n\t\t\t\t<div class=\"grid-item\">\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-early-years/img-1902.png\" alt=\"\" />\n\t\t\t\t</div>\n\t\t\t\t<div class=\"grid-item\">\n\t\t\t\t\t<h2>Becoming A Browns Town</h2>\n\t\t\t\t\t<p>In 1902, the Milwaukee Brewers moved to St. Louis with carriage-maker Robert Lee Hedges as the new owner. The club joined the National League&rsquo;s Cardinals to become the town&rsquo;s second (and soon favorite) baseball team. St. Louis loved baseball, and baseball loved it back.</p>\n\t\t\t\t\t<p>Giving a nod to the Cardinals&rsquo; former moniker (the Brown Stockings, for the color they wore), Hedges named his team the Browns. Then, he pinched several of the Redbirds&rsquo; notable players, including 1901 batting champ Jesse Burkett, future Hall-of-Fame shortstop Bobby Wallace and three of their best pitchers. Hedges rebuilt Sportsman&rsquo;s Park, which was first erected in 1881, the former home of the St. Louis Cardinals.</p>\n\t\t\t\t\t<p>With this, the Browns&rsquo; legacy — and a hometown rivalry — began.</p>\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2\">\n\t\t\t\t<h5>Inaugural Season</h5>\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-early-years/img-78-58.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p>The Browns&rsquo; 1902 record. Good enough for second in the American League.</p>\n\t\t\t\t<p><a href=\"/#/\" class=\"btn show-overlay\" data-overlay=\"almost\">The Story</a></p>\n\t\t\t</div>\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"sportsmans-park dark\">\n\n\t\t<div class=\"content\">\n\t\t\t<div class=\"section-1 contain\" data-theme=\"dark\" data-year=\"1909\" data-section-title=\"Sportsman&rsquo;s Park\">\n\t\t\t\t<h2>Sportsman&rsquo;s Park III</h2>\n\t\t\t\t<p>A third grandstand was built in Sportsman&rsquo;s Park in 1909, with the diamond anchored at the southwest corner. It was also the third concrete-and-steel structure of its kind in the majors. Here, the Browns would beat out the Cardinals - in attendance.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2\"  data-theme=\"dark\" data-year=\"1910\" data-section-title=\"To the cellar\">\n\t\t\t\t<h5>Loss Record</h5>\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-early-years/img-107.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p class=\"center\">The number of losses for the Browns, two years in a row. They finished 47-107 in 1910, and 45-107 in 1911.</p>\n\t\t\t</div>\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"branch-rickey\">\n\t\t<div class=\"content\">\n\t\t\t<div class=\"section-1\" data-theme=\"light\" data-year=\"1910\" data-section-title=\"THE TY COBB SCANDAL\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-early-years/img-up-in-arms.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p>St. Louis Post-Dispatch, October 1910, regarding Browns manager Jack O&rsquo;Connor&rsquo;s ploy to block Ty Cobb from the batting title</p>\n\t\t\t\t<p><a href=\"/#/\" class=\"btn show-overlay\" data-overlay=\"ty-cobb\">The Story</a></p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2 contain\" data-theme=\"light\" data-year=\"1914\" data-section-title=\"BRANCH RICKEY AS MANAGER\">\n\t\t\t\t<h2>Branch Rickey</h2>\n\t\t\t\t<p>In his first full season as the club&rsquo;s manager (1914), Branch Rickey helped the team improve their record to 71-82. The following year, Rickey left the field for the front office, transferring managing duties to Fielder Jones. Also in 1915, Rickey signed George Sisler to the Browns — perhaps the best thing to ever happen to the team.</p>\n\t\t\t</div>\n\t\t</div>\n\t</section>\n\n\t<section class=\"phil-ball dark\">\n\t\t<div class=\"content\">\n\n\t\t\t<div class=\"grid grid-middle contain section-1\" data-theme=\"dark\" data-year=\"1916\" data-section-title=\"Phil Ball\">\n\t\t\t\t<div class=\"grid-item\">\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-early-years/img-newspaper-clip.png\" alt=\"\" />\n\t\t\t\t</div>\n\t\t\t\t<div class=\"grid-item\">\n\t\t\t\t\t<h2>Sold To Ball</h2>\n\t\t\t\t\t<p>
5610In 1916, owner Robert Hedges sold the team to Philip Ball, previously the owner of the St. Louis Terriers (of the defunct Federal League).</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<img src=\"{{ Config.cdn }}images/history/the-early-years/img-wwi-interlude.png\" alt=\"\" class=\"wwi-interlude\" />\n\n\t\t\t<div class=\"section-2\" data-theme=\"dark\" data-year=\"1916-1922\" data-section-title=\"Ball&rsquo;s Blunders\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-early-years/img-balls-blunders.png\" alt=\"\" />\n\n\t\t\t\t<h5>Blunder 1</h5>\n\t\t\t\t<p>Fired Branch Rickey, who subsequently turned the Cardinals into one of baseball&rsquo;s premier teams, and later made history when he signed Jackie Robinson to the Brooklyn Dodgers.</p>\n\n\t\t\t\t<h5>Blunder 2</h5>\n\t\t\t\t<p>Allowed the Cardinals to share Sportsman&rsquo;s Park, freeing up enough funds for the Cards to build a farm system. </p>\n\n\t\t\t\t<h5>Blunder 3</h5>\n\t\t\t\t<p>Spent capital expanding Sportsman&rsquo;s Park in 1922, predicting a World Series there by 1926. Indeed, it came&hellip; but not for the Browns. The Cardinals faced the Yankees in the &lsquo;26 Fall Classic, and won.</p>\n\t\t\t</div>\n\t\t</div>\n\t</section>\n\n\t<section class=\"sizzlin-sisler\">\n\t\t<div class=\"content\">\n\n\t\t\t<div class=\"section-1\" data-theme=\"light\" data-year=\"1920\" data-section-title=\"SIZZLIN&rsquo; SISLER\">\n\t\t\t\t<h5>Sizzlin&rsquo; Sisler</h5>\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-early-years/img-407-257.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p>George Sisler&rsquo;s batting average and number of hits in 1920. The latter was a major league record for 84 years.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2 contain\" data-theme=\"light\" data-year=\"1922\" data-section-title=\"The Hot Squad\">\n\t\t\t\t<h2>The Hot Squad</h2>\n\t\t\t\t<p>In 1922, the Browns outfield was on fire. Ken Williams, Baby Doll Jacobson and Jack Tobin were all .300 or better, for the 4th season in a row. (They&rsquo;d continue the streak in 1923, and repeat the feat in 1925.) Williams not only led the league in RBIs and beat out Babe Ruth for the home run title, he was the founding member of the 30-30 Club — and the only member in the majors until 1956.</p>\n\t\t\t\t<p>That&rsquo;s not all. With a .420 average, future Hall-of-Famer George Sisler&rsquo;s bat was hotter than lightning. He hit safely in 41 consecutive games, stole 51 bases, and became the first official MVP for the American League. </p>\n\t\t\t\t<p>Further contributions to the Browns&rsquo; best-ever 93-61 record: Sisler and Williams were the top two base-stealers; Urban Shocker tallied up 24 Ws as his compatriots on the mound helped earn the league&rsquo;s lowest combined ERA.</p>\n\t\t\t</div>\n\t\t</div>\n\t</section>\n\n\t<section class=\"hot-squad\">\n\t\t<div class=\"content\">\n\t\t\t<h5>The Hot Squad</h5>\n\t\t\t<img src=\"{{ Config.cdn }}images/history/the-early-years/img-stlb-nyy.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t<p>One more win and the Browns would&rsquo;ve tied the Yanks for the 1922 AL pennant.</p>\n\t\t</div>\n\t</section>\n\n\t<a href=\"/#/history/the-bottom-dwellers\">\n\t\t<section class=\"next-section\" data-theme=\"\">\n\t\t\t<div class=\"content\">\n\t\t\t\t<p>Chapter 2</p>\n\t\t\t\t<h2>The Bottom Dwellers <span>&rarr;</span></h2>\n\t\t\t\t<p>1926-1941</p>\n\t\t\t</div>\n\t\t</section>\n\t</a>\n</div>",
5611		"the-bottom-dwellers": "<div class=\"border border-top\"></div>\n<div class=\"border border-right\"></div>\n<div class=\"border border-bottom\"></div>\n<div class=\"border border-left\"></div>\n\n<div class=\"inner\">\n\n\t<div class=\"timeline-bar\"></div>\n\n\t<section class=\"cardinals\">\n\n\t\t<div class=\"content\">\n\t\t\t<div class=\"grid grid-middle grid-padded section-1 contain\" data-theme=\"light\" data-year=\"1926\" data-section-title=\"Cardinals Win World Series\">\n\n\t\t\t\t<div class=\"grid-item\">\n\t\t\t\t\t<h2>Painting the Town Red</h2>\n\t\t\t\t\t<p>The 1926 World Series in Sportsman&rsquo;s Park saw the Cardinals beat the Yankees. This resulted in a fanbase coup — the Redbirds went on to win (or, win back) the hearts of local baseball fans. No longer was St. Louis a &ldquo;Browns Town.&rdquo;</p>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"grid-item image\">\n\t\t\t\t\t<img src=\"/images/history/the-bottom-dwellers/img-score-card.png\" alt=\"\" />\n\t\t\t\t</div>\n\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"section-2\" data-theme=\"light\" data-year=\"1926-27\" data-section-title=\"Browns lose 90 games\">\n\t\t\t\t<h5>90-loss Seasons</h5>\n\t\t\t\t<img src=\"/images/history/the-bottom-dwellers/img-26-27.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p>The Browns had two 90-loss seasons in a row — 92 in 1926, and 94 in 1927. Not surprisingly, they finished in seventh place both times.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-3\" data-theme=\"light\" data-year=\"1929\" data-section-title=\"Manush hits .355\">\n\t\t\t\t<img src=\"/images/history/the-bottom-dwellers/img-choke-up.png\" alt=\"\" />\n\t\t\t\t<p>Ty Cobb gave this fine piece of advice to Browns outfielder Heinie Manush in 1929. It must have done some good, because Manush averaged .355 that year, helping the Browns record their second straight winning season (79-73).</p>\n\t\t\t</div>\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"attendance-woes dark\">\n\t\t\n\t\t<div class=\"content\">\n\t\t\t<div class=\"section-1\" data-theme=\"dark\" data-year=\"1933\" data-section-title=\"just 33 attend Browns game\">\n\t\t\t\t<h5>
5611Attendance Woes</h5>\n\t\t\t\t<img src=\"/images/history/the-bottom-dwellers/img-33.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p class=\"contain\">After a string of years with 90+ losses, the Browns played one game for just 33 paying fans. The club faced a catch 22: they needed good players to attract a crowd, but they needed a crowd to afford good players.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2 contain\" data-theme=\"dark\" data-year=\"1933\" data-section-title=\"Browns tab hornsby\">\n\t\t\t\t\n\t\t\t\t<div class=\"grid grid-padded grid-middle\">\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"image\">\n\t\t\t\t\t\t<img src=\"/images/history/the-bottom-dwellers/img-card-back.png\" alt=\"\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h2>The Rajah</h2>\n\t\t\t\t\t\t<p>Phil Ball picked up Rogers Hornsby as player-manager in 1933, trying to lure Cardinals fans to Browns games. Hornsby holds the second best career batting average of all time (surpassed only by Ty Cobb). Despite his prowess, &ldquo;The Rajah&rdquo; didn&rsquo;t put himself in the lineup enough to scoop the Browns out of what would become a decade-long losing streak. However, he did hit the last home run of his career as a Brownie, helping his team beat the White Sox in a rare 15-10 victory.</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t\t<div class=\"section-3\" data-theme=\"dark\" data-year=\"1935\" data-section-title=\"Record low attendance\">\n\t\t\t\t\n\t\t\t\t<h5>Another depressing low</h5>\n\t\t\t\t<img src=\"/images/history/the-bottom-dwellers/img-80000.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p class=\"contain\">The depths of the Great Depression brought another famous low — the Browns&rsquo; worst single-season attendance record, woefully attained in 1935. This record still stands as a major league low.</p>\n\n\t\t\t</div>\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"barnes-dewitt\">\n\n\t\t<div class=\"content\">\n\t\t\t<div class=\"section-1\" data-theme=\"light\" data-year=\"1936\" data-section-title=\"Barnes &amp; Dewitt Buy Browns\">\n\t\t\t\t\n\t\t\t\t<div class=\"grid grid-padded grid-middle contain\">\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h2>Barnes &amp; Dewitt</h2>\n\t\t\t\t\t\t<p>New ownership took hold of the team in 1936 — Donald Lee Barnes became the majority stockholder and owner, and Bill DeWitt, Sr., became minority owner and general manager. The first few years remained rocky, but an upswing was on its way.</p>\n\t\t\t\t\t\t<div class=\"note\">\n\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/after-the-browns.png\" alt=\"\" class=\"show-overlay\" data-overlay=\"dewitt\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<img src=\"/images/history/the-bottom-dwellers/img-dewitt.png\" alt=\"\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2 contain\" data-theme=\"light\" data-year=\"1939\" data-section-title=\"Browns All-time worst record\">\n\t\t\t\t<h5>All-time worst</h5>\n\t\t\t\t<img src=\"/images/history/the-bottom-dwellers/img-43-111.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p class=\"contain\">The Browns&rsquo; all-time worst record put them 64 and a half games out of first for the 1939 season. The pitching staff’s combined ERA was 6.01, which could have been the main culprit.</p>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"section-3 contain\" data-theme=\"light\" data-year=\"1941\" data-section-title=\"Attack on pearl harbor\">\n\t\t\t\t\n\t\t\t\t<h2>Disastrous Timing</h2>\n\t\t\t\t<p>Owner Don Barnes was trying to move the team to Los Angeles, hoping for a better financial outlook. A league meeting to bestow final approval was slated for December 8th, 1941. The attack on Pearl Harbor happened on December 7th. Needless to say, the meeting didn’t happen, and the team stayed put.</p>\n\n\t\t\t</div>\n\t\t</div>\n\t</section>\n\n\t<section class=\"rebuilding dark\" data-theme=\"dark\" data-year=\"1941\" data-section-title=\"Browns Rebuild\">\n\n\t\t<div class=\"content\">\n\t\t\t\n\t\t\t<img src=\"/images/history/the-bottom-dwellers/img-rebuilding.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t<p class=\"contain\">New manager Luke Sewell establishes a rebuilding program in 1941. This would be the chance the Browns had always been waiting for.</p>\n\t\t\t\n\t\t</div>\n\n\t</section>\n\n\t<a href=\"/#/history/the-war-years\">\n\t\t<section class=\"next-section\" data-theme=\"\">\n\t\t\t<div class=\"content\">\n\t\t\t\t<p>Chapter 3</p>\n\t\t\t\t<h2>The War Years <span>&rarr;</span></h2>\n\t\t\t\t<p>1942-1946</p>\n\t\t\t</div>\n\t\t</section>\n\t</a>\n</div>",
5612		"the-war-years": "<div class=\"border border-top\"></div>\n<div class=\"border border-right\"></div>\n<div class=\"border border-bottom\"></div>\n<div class=\"border border-left\"></div>\n\n<div class=\"inner\">\n\n\t<div class=\"timeline-bar\"></div>\n\n\t<section class=\"roosevelt\">\n\n\t\t<div class=\"content\">\n\t\t\t<div class=\"section-1 contain\" data-theme=\"light\" data-year=\"1942\" data-section-title=\"Honesty\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-honestly.png\" alt=\"\" />\n\t\t\t\t<p class=\"attr\">President Franklin D. Roosevelt</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2\">\n\t\t\t\t<div class=\"grid grid-middle contain\">\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"text\">\n\t\t\t\t\t\t<p>The first World War had prematurely ended the 1918 baseball season, and many feared World War 2 would do the same. On January 15, 1942, President Roosevelt responded to a plea from Commissioner Kenesaw Mountain 
5612Landis, in what was come to be known as the &lsquo;Green Light Letter.&rdquo; Not only did he ensure the continuation of wartime baseball, he also pushed for more night games to give the hard-working people behind the war production effort a well-deserved break.</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-letter.png\" alt=\"\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-3 contain\" data-theme=\"light\" data-year=\"1942\" data-section-title=\"Building a Winner\">\n\t\t\t\t<h2>Building a Winner</h2>\n\t\t\t\t<p>With the go-ahead to keep playing, Luke Sewell got surgical with his 1942 roster. He got rid of lazy players and weak bats. He signed promising rookies. And he traded for veterans with positive attitudes and overlooked power. Some of the gems Sewell brought on board included Don Gutteridge, Vern Stephens, Ellis Clary, Steve Sundra, and Al Hollingsworth.</p>\n\t\t\t\t<p>The Browns lost some players to the war effort, but they didn&rsquo;t lose star-level power like Joe Dimaggio, Hank Greenberg or Ted Williams. So, as the other teams in the league said goodbye to their key players, the Browns&rsquo; chances of winning got better and better.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-4\">\n\t\t\t\t<h5>1942 SEASON</h5>\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-82-69.png\" alt=\"\" class=\"big-stuff\">\n\t\t\t\t<p>The 1942 Browns brought home the team&rsquo;s first winning season since 1929.</p>\n\t\t\t</div>\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"cold-springs dark\">\n\t\t\n\t\t<div class=\"content\">\n\t\t\t<div class=\"section-1 contain\" data-theme=\"dark\" data-year=\"1943\" data-section-title=\"Cold Springs\">\n\t\t\t\t<h2>Cold Springs</h2>\n\t\t\t\t<p>From 1943 to 1945, Commissioner Landis required all Major League Teams to stay close to home for spring training, explaining that long-distance travel resources were best left to those involved in the war effort. The Browns trained just 100 miles south of St. Louis in Cape Girardeau, Missouri. Theirs was a much better plight than the many northeast teams, who made training grounds out of airport hangars, horse stables, hotel rooms, and — when the baseball fields were too frosty — golf fairways.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2\" data-theme=\"dark\" data-year=\"1943\" data-section-title=\"Balata Ball\">\n\t\t\t\t<div class=\"grid grid-middle contain\">\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"text\">\n\t\t\t\t\t\t<h2>Balata Ball</h2>\n\t\t\t\t\t\t<p>Rubber was in high demand for the war, so regular baseballs got the shaft. For the 1943 season, major leaguers had to play with a &lsquo;balata ball,&rsquo; which had a hard plastic core and didn&rsquo;t travel as far. Lower scoring games were common. Batters were not thrilled.</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-ball.png\" alt=\"\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"infield\">\n\t\t\n\t\t<div class=\"content\">\n\t\t\t\n\t\t\t<div class=\"section-1 contain\" data-theme=\"light\" data-year=\"1944\" data-section-title=\"All 4-F Infield\">\n\t\t\t\t<h2>All 4-F Infield</h2>\n\t\t\t\t<p>Every player on the 1944 Browns infield was 4-F, or excused from military service for one reason or another.</p>\n\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-infield.png\" alt=\"\" />\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2\">\n\t\t\t\t<h2>9 Straight W&rsquo;s</h2>\n\t\t\t\t<p>The Browns opened the 1944 season with a bang — or a crack — or a whopping, righteous blast — nine straight wins.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-3\">\n\t\t\t\t<h2>Almost Perfect</h2>\n\t\t\t\t<p>On May 26, 1944, Nels Potter retired 23 batters in a row. Sadly, Jim Tabor, of the opposing Red Sox, got a hit in the 8th to dash Potter&rsquo;s hopes of a perfect game.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-4 contain\" data-theme=\"light\" data-year=\"1944\" data-section-title=\"The 1st Illegal Pitcher\">\n\n\t\t\t\t<div class=\"grid grid-middle\">\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"image\">\n\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-pitcher.png\" alt=\"\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h2>The 1st Illegal Pitcher</h2>\n\t\t\t\t\t\t<p>Browns pitcher Nels Potter was caught &lsquo;moistening his fingers&rsquo; before every pitch in a game against the Yankees on July 20, 1944. He was suspended for 10 games, becoming the first player in MLB history to be suspended for throwing an illegal pitch.</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t</div>\n\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"scrabeenies dark\">\n\t\t\n\t\t<div class=\"content\">\n\t\t\t\n\t\t\t<div class=\"section-1\" data-theme=\"dark\" data-year=\"1944\" data-section-title=\"Scrabeenies\">\n\t\t\t\t<div class=\"contain\">\n\t\t\t\t\t<h2>Scrabeenies</h2>\n\t\t\t\t\t<p>Ellis Clary crowned himself the &ldquo;manager&rdquo; of the Browns&rsquo; backup players, who called themselves the scrabeenies. Most of these utility guys didn&rsquo;t show their stuff when given the chance. But Al Zarilla went 2 for 2 in a July game against the Red Sox, earning himself a more frequent spot in the lineup for the remainder of the season. So
5612on after, this former scrabeenie pounded out an 11-game hitting streak.</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-25000.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p class=\"contain\">Every major league team was required to host one game where all net proceeds would be given to a national war relief organization. On July 26, 1944, the Browns played the Philadelphia Athletics — in front of their biggest crowd since their first night game in 1940 — and raised $25,000.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-3\" data-theme=\"dark\" data-year=\"1944\" data-section-title=\"70 Days In First\">\n\t\t\t\t<h2>70 Days in 1st</h2>\n\t\t\t\t<p>On August 8th, the Browns broke their previous record, set in 1922, for consecutive days leading the American League.</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-4 contain\" data-theme=\"dark\" data-year=\"1944\" data-section-title=\"Fight!\">\n\t\t\t\t\n\t\t\t\t<div class=\"grid grid-padded grid-middle\">\n\t\t\t\t\t\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-fight.png\" alt=\"\" class=\"flush-bottom\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<p class=\"flush-bottom\">On September 21, 1944, the Browns were in the last game of the last series against the Senators. A fight broke out between Browns catcher Tom Turner and Senators outfielder Roberto Ortiz. The Senators would go on to play the Tigers, who the Browns were racing for first-place. So, when Ortiz broke his hand in the fight with Turner, the Browns weren&rsquo;t too happy about it, either.</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t\t<div class=\"section-5\" data-theme=\"dark\" data-year=\"1944\" data-section-title=\"The Heat Is On\">\n\t\t\t\t\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-84-64.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p>The Browns and the Tigers were tied for first with an identical record. There were 6 games left in the season. The heat was on.</p>\n\n\t\t\t</div>\n\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"pennant\">\n\t\t\n\t\t<div class=\"content\" data-theme=\"light\" data-year=\"1944\" data-section-title=\"The Clincher\">\n\t\t\t\n\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-clincher.png\" alt=\"\" class=\"big-stuff\" />\n\n\t\t\t<div class=\"section-1\">\n\t\t\t\t<div class=\"highlight\">\n\t\t\t\t\t<h5>Highlight 1</h5>\n\t\t\t\t\t<p>Wild man Sig Jakucki took the mound for the Browns.</p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"highlight\">\n\t\t\t\t\t<h5>Highlight 2</h5>\n\t\t\t\t\t<p>He retired the first two Yanks.</p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"highlight\">\n\t\t\t\t\t<h5>Highlight 3</h5>\n\t\t\t\t\t<p>The Browns were hitless through the third. Key errors put the Yankees up 2-0.</p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"highlight\">\n\t\t\t\t\t<h5>Highlight 4</h5>\n\t\t\t\t\t<p>Chet Laabs crushed a fastball over the bleachers to tie the game.</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-scoreboard.png\" alt=\"\" class=\"big-stuff\" />\n\n\t\t\t<div class=\"section-2\" data-theme=\"light\" data-year=\"1944\" data-section-title=\"The Fighten’st Team Ever To Wear A Uniform!\">\n\t\t\t\t<div class=\"highlight\">\n\t\t\t\t\t<h5>Highlight 5</h5>\n\t\t\t\t\t<p>Bottom 5, Laabs was up for his third at-bat, and ripped another 2-run homer.</p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"highlight\">\n\t\t\t\t\t<h5>Highlight 6</h5>\n\t\t\t\t\t<p>In the remaining innings, Jakucki only allowed one more batter to reach 3rd.</p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"highlight\">\n\t\t\t\t\t<h5>Highlight 7</h5>\n\t\t\t\t\t<p>The Browns led 5-2 into the ninth. Johnny Lindell blasted a pitch from Jakucki, but it was caught for a long out by Browns right fielder Gene Moore. The crowd exhaled.</p>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"highlight\">\n\t\t\t\t\t<h5>Highlight 8</h5>\n\t\t\t\t\t<p>Down to the final out, Oscar Grimes spikes a high fly ball into foul territory. Browns first baseman George Mc
5612Quinn finds it in his glove.</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-pennant.png\" alt=\"\" class=\"big-stuff\" />\n\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"street-car dark\">\n\t\t\n\t\t<div class=\"content\">\n\t\t\t\n\t\t\t<div class=\"section-1\" data-theme=\"dark\" data-year=\"1944\" data-section-title=\"The Streetcar Series\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-streetcar.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2\">\n\t\t\t\t\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-world-series.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<p>Stan Musial, St. Louis Cardinals</p>\n\n\t\t\t</div>\n\n\t\t\t<div class=\"section-3\">\n\t\t\t\t\n\t\t\t\t<div class=\"grid contain grid-middle\" data-theme=\"dark\" data-year=\"1944\" data-section-title=\"Shared Turf\">\n\t\t\t\t\t\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h2>Shared Turf</h2>\n\t\t\t\t\t\t<p>The Cardinals and the Browns both called Sportsman&rsquo;s Park home. So, both teams would have the home team advantage&hellip; The Cards for the first two and the last two games, and the Browns for the three in the middle.</p>\n\t\t\t\t\t\t<p>The teams shared more than just the stadium. Luke Sewell and Cardinals manager Billy Southworth shared an apartment in St. Louis. They agreed that Sewell would stay there during the Series, and Southworth would reside at a hotel until it was over.</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div class=\"image\">\n\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-poster.png\" alt=\"\" />\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t\t<div class=\"section-4\" data-theme=\"dark\" data-year=\"1944\" data-section-title=\"The World Series\">\n\n\t\t\t\t<div class=\"carousel\">\n\t\t\t\t\t<div class=\"arrow-right\"><img src=\"{{ Config.cdn }}images/arrow-right.png\" alt=\"\" /></div>\n\t\t\t\t\t<div class=\"arrow-left\"><img src=\"{{ Config.cdn }}images/arrow-left.png\" alt=\"\" /></div>\n\t\t\t\t\t<div class=\"slides\">\n\t\t\t\t\t\t<div class=\"slide\">\n\t\t\t\t\t\t\t<div class=\"wrapper\">\n\t\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-game-1.png\" alt=\"\" />\n\t\t\t\t\t\t\t\t<p>No player on the 1944 Browns roster had ever made it to a World Series. The veteran Cardinals were favored to win, but the Browns didn&rsquo;t care. They came out with a fighting spirit. Denny Galehouse out-pitched Mort Cooper and the Cardinals. George McQuinn hit a two-run jack in the fourth inning. And the Browns won it, 2-1.</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"slide\">\n\t\t\t\t\t\t\t<div class=\"wrapper\">\n\t\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-game-2.png\" alt=\"\" />\n\t\t\t\t\t\t\t\t<p>The Browns were hoping luck stayed on their side. Missouri Senator, Democratic Party vice presidential nominee and future president Harry S. Truman was in the audience. The St. Louis Beer Company had given each player a silver horseshoe to hang over their lockers. However, Nelson Potter, who normally didn&rsquo;t shave before he started a game, took the mound clean-shaven. </p>\n\t\t\t\t\t\t\t\t<p>The Cardinals led 2-0 through the 6th, thanks to Blix Donnelly&rsquo;s stellar arm and a series of errant defensive plays. With 2 outs in the 7th, the Browns tied it up. The game stretched until the 11th, when Cardinals backup catcher and pinch hitter Ken O&rsquo;Dea hit a game-winning RBI single to end the game. </p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"slide\">\n\t\t\t\t\t\t\t<div class=\"wrapper\">\n\t\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-game-3.png\" alt=\"\" />\n\t\t\t\t\t\t\t\t<p>Still at Sportsman&rsquo;s Park, but now the Browns were the home team. The advantage served them well — Browns pitcher Jack Kramer gave up only 7 hits, and struck out 10 batters.</p>\n\t\t\t\t\t\t\t\t<p>It wasn&rsquo;t all smooth sailing, though. Browns shortstop Vern Stephens booted a ground ball, resulting in a two-base error that eventually let the Cards score 1 in the first. The Browns came up empty-handed in the second inning with a bases-loaded strikeout. </p>\n\t\t\t\t\t\t\t\t<p>The Browns seemed to crack the code in the third, playing small ball and scoring 3 on singles, eventually landing a 6-2 victory. To that point, all of the Browns&rsquo; 10 runs in the series had been scored on 2 outs. </p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"slide\">\n\t\t\t\t\t\t\t<div class=\"wrapper\">\n\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-game-4.png\" alt=\"\" />\n\t\t\t\t\t\t\t\t<p>The Cardinals had Sig Jakucki&rsquo;s number for Game 4. The 35-year-old pitcher had been out of baseball for 5 years prior to the 1944 season, but he&rsquo;d still brought in 13 wins that year. But most of this game was robbery.</p> \n\t\t\t\t\t\t\t\t<p>Stan Musial took a big cut at a low fastball, and sent it out of the park. Double plays and an over-the-shoulder 
5612catch suffocated the Browns offense. And an error made it 4-0, Cardinals, in the 3rd. Jakucki was pulled in the bottom of that inning. Outfielder Chet Laabs hit into a double play that scored the Browns&rsquo; one and only run, and the Redbirds went on to win it 5-1.</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"slide\">\n\t\t\t\t\t\t\t<div class=\"wrapper\">\n\t\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-game-5.png\" alt=\"\" />\n\t\t\t\t\t\t\t\t<p>With the series tied 2-2, the Browns were hoping that the Galehouse-Cooper matchup would be a repeat of their success in the first game. Through 5, it was a pitcher&rsquo;s duel, with no hits for either team. </p>\n\t\t\t\t\t\t\t\t<p>Then, Ray Sanders hit a solo shot onto the right field roof — the first homer Galehouse had allowed since August 6th. Galehouse took it in stride, until Danny Litwhiler followed suit in the 8th. Cooper&rsquo;s pitching struck out 12 men, just one shy of the record at the time, as he shut out the Browns, 2-0.</p> \n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"slide\">\n\t\t\t\t\t\t\t<div class=\"wrapper\">\n\t\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-game-6.png\" alt=\"\" />\n\t\t\t\t\t\t\t\t<p>It was a frosty night. Nelson Potter was back on the Browns mound, and Max Lanier threw for the Cards (who were the home team once again). The Browns took an early lead in the second within RBI single by George McQuinn, but they couldn&rsquo;t hold on to the lead. A walk and a handful of singles put the Cardinals on top in the fourth inning, and that&rsquo;s where they stayed. The Browns said goodbye to their &ldquo;Cinderella season,&rdquo; and their last-ever appearance in a World Series, with a 3-1 loss.</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"war-ends\">\n\t\t\n\t\t<div class=\"content\">\n\t\t\t\n\t\t\t<div class=\"section-1\" data-theme=\"light\" data-year=\"1946\" data-section-title=\"The War Ends\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-1945.png\" alt=\"\" class=\"big-stuff\" />\n\t\t\t\t<div class=\"contain\">\n\t\t\t\t\t<p>Although the Browns didn&rsquo;t win the World Series, they unbelievably captured the 1944 pennant. The next year, they still had enough steam to contend in the pennant race, finishing 6 games back to take 3rd in the American League. Also in 1945, Don Barnes sold the Browns to Richard Muckerman.</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2 contain\">\n\t\t\t\t<div class=\"grid grid-padded grid-middle\">\n\t\t\t\t\t<div class=\"grid-item image\">\n\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-war-years/img-crowd.png\" alt=\"\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"grid-item\">\n\t\t\t\t\t\t<h2>THE WAR ENDS</h2>\n\t\t\t\t\t\t<p>Many of the baseball greats who had gone off to serve in World War II had returned home for the 1946 season, and were returning to the field. The rest of the league&rsquo;s talent was replenished, and the Browns&rsquo; best years were put behind them. The 1947 and 1948 seasons saw the Browns&rsquo; return to an ever-so-familiar place — last in the American League. Both years ended with 59 wins and more than 90 losses.</p>\t\t\t\t\t\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</div>\n\n\t</section>\n\n\t<a href=\"/#/history/the-bill-veeck-era\">\n\t\t<section class=\"next-section\" data-theme=\"\">\n\t\t\t<div class=\"content\">\n\t\t\t\t<p>Chapter 4</p>\n\t\t\t\t<h2>The Bill Veeck Era <span>&rarr;</span></h2>\n\t\t\t\t<p>1949-1953</p>\n\t\t\t</div>\n\t\t</section>\n\t</a>\n</div>",
5613		"the-bill-veeck-era": "<div class=\"border border-top\"></div>\n<div class=\"border border-right\"></div>\n<div class=\"border border-bottom\"></div>\n<div class=\"border border-left\"></div>\n\n<div class=\"inner\">\n\n\t<div class=\"timeline-bar\"></div>\n\n\t<section class=\"dewitt-brothers\">\n\n\t\t<div class=\"content\">\n\t\t\t<div class=\"section-1 contain\" data-theme=\"light\" data-year=\"1948\" data-section-title=\"The Dewitt Bros. buy the browns\">\n\n\t\t\t\t<h2>The DeWitt Brothers</h2>\n\t\t\t\t<p>Owner Richard Muckerman had proven to be ineffective during his 4 seasons as owner (1945-1948). This was quite a disappointment, following the Browns&rsquo; 1944 pennant victory. In hopes to resurrect the team&rsquo;s potential, Bill DeWitt and his brother, Charlie, bought the Browns club after the 1948 season.</p>\n\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"section-2 contain\" data-theme=\"light\" data-year=\"1949\" data-section-title=\"Browns lose 90 games\">\n\t\t\t\t<div class=\"grid grid-middle\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-senators.jpg\" alt=\"\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h2>Better Than the Senators</h2>\n\t\t\t\t\t\t<p>That was about the only recognition the Browns could muster up for the &lsquo;49 season. They finished in 7th place with a 53-101 record, just a few games better than the 50-104 Washington Senators.</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"veeck-background dark\">\n\t\t\n\t\t<div class=\"content\">\n\t\t\t<div class=\"section-1 contain\" data-theme=\"dark\" data-year=\"1950\" data-section-title=\"Bill Veeck buys the Browns\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-quote-beautiful.png\" alt=\"\" />\n\t\t\t\t<p class=\"attr\">- Bill Veeck</p>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-2 contain\">\n\t\t\t\t<h2>
5613Bill Veeck: Background</h2>\n\t\t\t\t<p>The DeWitts sold the Browns to Bill Veeck in 1951. Veeck was coming off the best and most tumultuous times of his life. He&rsquo;d signed the first black player to the American League in 1947. A year later, he signed Satchel Paige, the oldest rookie in the majors. He also led the Cleveland Indians to the team&rsquo;s first pennant and World Series title since 1920. Sadly, his first wife divorced him in 1949. Strapped for cash, he sold the Indians.</p>\n\t\t\t\t<p>Things were on the upswing for him by 1950 — he married his new true love, Mary Frances Ackerman, and bought 80% stake in the Browns organization.</p>\n\n\t\t\t\t<div class=\"note\">\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/after-the-browns.png\" alt=\"\" class=\"show-overlay\" data-overlay=\"veeck\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div data-theme=\"dark\" data-year=\"1951\" data-section-title=\"Veeck competes with Cardinals\">\n\t\t\t\t<div class=\"section-3 contain\">\n\t\t\t\t\t\n\t\t\t\t\t<div class=\"grid grid-middle\">\n\t\t\t\t\t\t\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-program.png\" alt=\"\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h2>Two&rsquo;s a Crowd</h2>\n\t\t\t\t\t\t\t<p>Since Day 1, Bill Veeck saw the Cardinals as a threat, not just a friendly rivalry. He tried to push them out — or at least stir up some drama at their shared home park. Veeck brought three former Cardinals over to the Browns: Rogers Hornsby and Marty Marion as coaches, and Dizzy Dean as announcer. He also decorated Sportsman&rsquo;s Park solely with Browns memorabilia.</p>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"section-4 contain\">\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-quote-argyin.png\" alt=\"\" />\n\t\t\t\t\t<p class=\"attr\">- Dizzy Dean</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t</section>\n\n\t<section class=\"free-beer\">\n\t\t<div class=\"content\">\n\t\t\t<div class=\"section-1 contain\" data-theme=\"light\" data-year=\"1951\" data-section-title=\"Free Beer Night\">\n\t\t\t\t<h2>Free Beer</h2>\n\t\t\t\t<p>For his first game as owner, Bill Veeck gave everyone in the ballpark a free beer or soda. Just imagine what he&rsquo;d think of ballpark prices today.</p>\n\t\t\t</div>\n\n\t\t\t<div data-theme=\"light\" data-year=\"1951\" data-section-title=\"Eddie Gaedal walks\">\n\t\t\t\t<div class=\"section-2 contain\">\n\t\t\t\t\t<div class=\"grid grid-middle grid-padded\">\n\t\t\t\t\t\t<div class=\"image\">\n\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-1-8.png\" alt=\"\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<p>Of all of Veeck&rsquo;s radical promotions — or, in his eyes, creative ways to attract a much-needed crowd — this little one left a big impact on fans&rsquo; memories. Eddie Gaedel, standing just 3-foot-7, appeared as a pinch hitter on August 19, 1951. Wearing the number ⅛ on a jersey made for Bill DeWitt&rsquo;s son, Gaedel drew four straight balls. His strike zone was tiny, as were his legs. He was replaced by a pinch runner, but his 1.000 career on-base percentage remains in tact.</p>\t\t\t\t\t\t\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"section-3\">\n\t\t\t\t\t<h5>A small threat</h5>\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-1000000.png\" alt=\"\" />\n\t\t\t\t\t<p>The life insurance policy Bill Veeck took out for Eddie Gaedel. Veeck threatened Gaedel with his life if he dared to swing the bat.</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</section>\n\n\t<section class=\"dreamers dark\">\n\t\t<div class=\"content\">\n\t\n\t\t\t<div data-theme=\"dark\" data-year=\"1951\" data-section-title=\"Fans manage from stands\">\n\t\t\t\t<div class=\"section-1 contain\">\n\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-quote-dreamers.png\" alt=\"\" />\n\t\t\t\t\t<p class=\"attr\">- Bill Veeck</p>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div class=\"section-2 contain\">\n\t\t\t\t\t<div class=\"grid grid-padded grid-middle\">\n\t\t\t\t\t\t<div class=\"image\">\n\t\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-grandstand.jpg\" alt=\"\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h2>Grandstand Manager&rsquo;s Day</h2>\n\t\t\t\t\t\t\t<p>No, the managers weren&rsquo;t in the stands. No, the grandstands didn&rsquo;t have a new manager. Indeed, Bill Veeck appointed the fans in the grandstand to make managerial decisions throughout the game. They w
5613ould vote on whether a player should bunt, steal a base, change pitchers, and more, by holding up signs that read “YES” or “NO.” The Browns went on to win that game 5-3, breaking their 4-game losing streak.</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</section>\n\n\t<section class=\"california\">\n\t\t<div class=\"content\">\n\n\t\t\t<div class=\"section-1 contain\" data-theme=\"light\" data-year=\"1952\" data-section-title=\"Veeck attempts move to L.A.\">\n\t\t\t\t<h2>California or Bust</h2>\n\t\t\t\t<p>Despite all of his efforts to bring in a crowd, Bill Veeck couldn&rsquo;t bring home enough wins. The 1951 season ended with a 52-102 record. The &lsquo;52 season was just a shade better at 64-90. Veeck tried to move the Browns to Los Angeles, but with most other teams in the Midwest or on the East Coast, the travel expenses — and the ire of other team owners — were too much for MLB execs to approve it.</p>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div class=\"section-2 contain\" data-theme=\"light\" data-year=\"1953\" data-section-title=\"Anheuser-Busch buys Cardinals\">\n\t\t\t\t<div class=\"grid grid-padded grid-middle\">\n\t\t\t\t\t<div class=\"image\">\n\t\t\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-anheuser.png\" alt=\"\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h2>How Beer Wrecked Veeck</h2>\n\t\t\t\t\t\t<p>Cardinals owner Fred Saigh was forced to sell the team after he was convicted of income tax evasion. It looked like Veeck had won&hellip; until August Busch, Jr., owner of Anheuser-Busch, came to bat for the Redbirds. Veeck knew the Cardinals were here to stay, and he was no match for the financial, political and social power of the Busch family.</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"section-3 contain\" data-theme=\"light\" data-year=\"1953\" data-section-title=\"Veeck sells Park to Cards\">\n\t\t\t\t\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-quote-villian.png\" alt=\"\" />\n\t\t\t\t<p class=\"attr\">– Bill Veeck in his autobiography, Veeck – As In Wreck: The Autobiography of Bill Veeck</p>\n\t\t\t\t<p>Veeck was running out of options, and running out of cash. He sold Sportsman&rsquo;s Park to August Busch, Jr., for $800,000 during the 1953 season.</p>\n\n\t\t\t</div>\n\n\t\t\t<div class=\"section-4 contain\" data-theme=\"light\" data-year=\"1953\" data-section-title=\"Browns Sold and moved to Baltimore\">\n\t\t\t\t\n\t\t\t\t<h2>Baltimore-Bound</h2>\n\t\t\t\t<p>Bill Veeck wanted to move the team to Baltimore. But the American League decision-makers were still so riled up about Veeck&rsquo;s antics, they denied the transfer. It&rsquo;s not that they didn&rsquo;t want the team to move — they simply didn&rsquo;t want Veeck in Baltimore. Veeck&rsquo;s only move was to sell all of his shares to a Baltimore attorney and baseball-lover, Clarence Miles.</p>\n\n\t\t\t</div>\n\t\t</div>\n\t</section>\n\n\t<section class=\"final dark\" data-theme=\"dark\" data-year=\"1953\" data-section-title=\"The End\">\n\t\t\n\t\t<div class=\"content\">\n\t\t\t<div class=\"contain\">\n\t\t\t\t<img src=\"{{ Config.cdn }}images/history/the-veeck-era/img-final-tally.png\" alt=\"\" />\n\t\t\t</div>\n\t\t</div>\n\n\t</section>\n\n\t<a href=\"/#/players\">\n\t\t<section class=\"next-section\" data-theme=\"\" data-year=\"\" data-section-title=\"\">\n\t\t\t<div class=\"content\">\n\t\t\t\t<p>More Browns History</p>\n\t\t\t\t<h2>See The Players &rarr;</h2>\n\t\t\t</div>\n\t\t</section>\n\t</a>\n\n</div>"
5614	},
5615
5616	init: function( routeData, onComplete ) {
5617
5618		var id = routeData.params.id;
5619
5620		//- set up container
5621		$.addClass(id + ' page', this.div);
5622
5623		$.css(this.div, {
5624			padding: 0
5625		});
5626
5627		var nav = this.nav = $.select('.nav-controller', document.body);
5628		$.removeClass(nav, 'dark');
5629
5630		//- save current section
5631		var id = this.id = routeData.params.id;
5632		this.template = this.templates[ id ];
5633
5634		var sectionData = this.data = _.findWhere(_data.sections, { key: id });
5635		sectionData.Config = Config;
5636
5637		//- render main view
5638		this.render( sectionData );
5639
5640		//- build hero
5641		this.hero = new Hero( sectionData );
5642
5643		//- build timeline
5644		this.timeline = new HistoryTimeline();
5645
5646		//- render hero and timeline
5647		$.prepend( this.hero.div, this.div);
5648		$.prepend( this.timeline.div, this.div);
5649
5650		//- add to the scene
5651		$.append(this.div, Stage);
5652
5653		//- save DOM queries
5654		this.wrapper = 		$.select('.inner', this.div);
5655		this.sections = 	$.select('section', this.div);
5656		this.borders = 		$.select('.border', this.div);
5657		this.years = 		$.select('[data-year]', this.div);
5658		this.timelineBar = 	$.select('.timeline-bar', this.div);
5659		this.carousels = 	[];
5660
5661		this.currentYear = 		null;
5662		this.currentSection = 	null;
5663
5664		//- create carousel(only one of them...)
5665		var c = $.select('.carousel', this.div);
5666
5667		for( var i = 0; i < c.length; i ++ ) {
5668			this.carousels[ i ] = new Carousel( c[ i ], {} );
5669		}
5670
5671		//- save scroll position
5672		this.scr = 0;
5673
5674		//- wire event listeners
5675		this.addListeners();
5676
5677		//- set up renderer for smooooooooooth scrolling
5678		this.renderer = new SmoothScroll( this.onRender.bind(this) );
5679
5680		//- set scroll limits on renderer
5681		this.resize();
5682
5683		Velocity.hook(this.timeline.div, "opacity", 0);
5684
5685		this.overlay.init( this );
5686
5687		//- animate in
5688		onComplete();
5689	},
5690
5691	addListeners: function() {
5692
5693		var _this = this;
5694		var bug = $.select('.scroll', this.div);
5695		var wrapper = $.select('.inner', this.div);
5696		var max = Math.max(0, wrapper[0].scrollHeight);
5697
5698		$.on(bug[ 0 ], 'click', function() {
5699
5700			_this.renderer.setTarget(window.innerHeight * -1);
5701
5702			setTimeout(function() {
5703				_this.scrollCheck();
5704			}, 350);
5705		});
5706
5707		var handler = function(e) {
5708
5709			if( $.hasClass(e.target, 'show-overlay') ) {
5710
5711				e.preventDefault();
5712
5713				var section = $.attr(e.target, 'data-overlay');
5714				var data = _this.data[ 'overlayData' ][ section ];
5715
5716				_this.overlay.populate(data, 'history-section');
5717			}
5718
5719			if( $.hasClass(e.target, 'close') ) {
5720
5721				_this.overlay.animateOut();
5722			}
5723		};
5724
5725		if( Device.system.touch ) {
5726			$.on(this.div, 'touchend', handler);
5727		} else {
5728			$.on(this.div, 'click', handler);
5729		}
5730
5731		VirtualScroll.on(function(e) {
5732			_this.scrollCheck(e);
5733		});
5734	},
5735
5736	scrollCheck: Util.debounce(function(e) {
5737
5738		threshold = (e.deltaY > 0) ? 0 : 0.8;
5739
5740		if( this.scr > -100 ) {
5741
5742			$.removeClass(this.borders, 'light dark');
5743			$.removeClass(this.timeline.div, 'light dark');
5744			$.removeClass(this.timelineBar, 'light dark');
5745			$.removeClass(this.nav, 'light dark');
5746
5747			this.currentSection = 'hero';
5748			this.currentYear = '';
5749		}
5750
5751		if( this.scr <= (window.innerHeight * -0.65) ) {
5752
5753			if( !this.timeline.active ) {
5754
5755				this.timeline.active = true;
5756
5757				Velocity(this.timeline.div, {
5758					opacity: 1
5759				}, {
5760					duration: 1000,
5761					easing: 'easeOutCubic',
5762				});
5763			}
5764		} else {
5765
5766			if( this.timeline.active ) {
5767
5768				this.timeline.active = false;
5769				
5770				Velocity(this.timeline.div, {
5771					opacity: 0
5772				}, {
5773					duration: 250,
5774					easing: 'easeOutCubic',
5775				});
5776			}
5777		}
5778
5779		//- check viewport vis for sections
5780		for( var i = 0; i < this.sections.length; i ++ ) {
5781
5782			var _this = this.sections[ i ];
5783
5784			if( isVisible(_this) && _this !== this.currentSection ) {
5785
5786				this.currentSection = _this;
5787				var content = $.select('.content', _this);
5788
5789				if( !$._bonzo(content).data('visible') ) {
5790
5791					$._bonzo(content).data('visible', true);
5792
5793					Velocity(content, {
5794						opacity: [ 1, 0 ],
5795						translateY: [ 0, 50 ]
5796					}, {
5797						duration: 1200,
5798						easing: 'easeOutCubic',
5799						delay: 250
5800					});
5801				}
5802			}
5803		}
5804
5805		//- check viewport vis for items tagged with years
5806		for( var i = 0; i < this.years.length; i ++ ) {
5807
5808			var _this = this.years[ i ];
5809
5810			if( isVisible(_this) && this.currentYear !== _this ) {
5811
5812				// console.log(_this);
5813
5814				this.currentYear = _this;
5815
5816				var year = $.attr(_this, 'data-year');
5817				var title = $.attr(_this, 'data-section-title');
5818				var theme = $.attr(_this, 'data-theme') || '';
5819				var navTheme = ( theme == "dark" ) ? '' : 'dark';
5820
5821				$.removeClass(this.borders, 'light dark');
5822				$.removeClass(this.timeline.div, 'light dark');
5823				$.removeClass(this.timelineBar, 'light dark');
5824				$.removeClass(this.nav, 'light dark');
5825
5826				$.addClass(theme, this.borders);
5827				$.addClass(theme, this.timeline.div);
5828				$.addClass(theme, this.timelineBar);
5829				$.addClass(navTheme, this.nav);
5830				
5831				this.timeline.update(year, title);
5832			}
5833		}
5834	}, 15),
5835
5836	onRender: function( scr ) {
5837
5838		this.scr = scr;
5839
5840		this.hero.onRender(scr);
5841
5842		$.transform(this.wrapper, {
5843			y: scr
5844		});
5845	},
5846
5847	animateOut: function( onComplete ) {
5848
5849		Velocity(this.div, {
5850			opacity: [ 0, 1 ]
5851		}, {
5852			duration: 1000,
5853			complete: onComplete
5854		});
5855
5856		this.hero.animateOut();
5857		this.renderer.stopRender();
5858	},
5859
5860	animateIn: function( onComplete ) {
5861
5862		var _this = this;
5863
5864		setTimeout(function() {
5865			_this.resize();
5866		}, 100);
5867
5868		Velocity(this.div, {
5869			opacity: [ 1, 0 ]
5870		}, {
5871			duration: 1000,
5872			complete: onComplete,
5873			easing: 'linear'
5874		});
5875
5876		this.renderer.startRender();
5877		this.hero.animateIn();
5878	},
5879
5880	resize: function( w, h ) {
5881
5882		this.hero.resize( w, h );
5883
5884		var wrapper = $.select('.inner', this.div);
5885		var max = Math.max(0, wrapper[0].scrollHeight);
5886
5887		this.renderer.setLimits((max * -1), 0);
5888
5889		for( var i = 0; i < this.carousels.length; i ++ ) {
5890			Util.debounce(this.carousels[ i ].resize( w, h ), 1000, false);
5891		}
5892	}
5893});
5894
5895module.exports = HistoryView;
5896},{"./../Config":1,"./../Data":2,"./../components/Carousel":5,"./../components/DOM":6,"./../components/Device":7,"./../components/HistoryHero":10,"./../components/HistoryTimeline":11,"./../components/Overlay":15,"./../components/SmoothScroll":19,"./../components/Utils":22,"./../components/View":23,"./../components/VirtualScroll":26,"./../components/oop/Class":28,"underscore":53,"velocity-animate":54}],33:[function(require,module,exports){
5897
5898
5899var Class = require('./../components/oop/Class');
5900var View = require('./../components/View');
5901var Velocity = require('velocity-animate');
5902var $ = require('./../components/DOM');
5903
5904var Config = require('./../Config');
5905var _data = require('./../Data').historySection;
5906var Util = require('./../components/Utils');
5907var SnappyScroll = require('./../components/SnappyScroll');
5908var Shuffle = require('./../components/ShuffleLetters')();
5909
5910var HistoryView = new Class({
5911
5912	name: "history-view",
5913	Extends: View,
5914	template: "\n<div class=\"page-title\">\n\t<h1>{{ title }}</h1>\n</div>\n\n<div class=\"scroll-bug\">\n\t<div><img src=\"{{ config.cdn }}images/bg/icn-right-arrow.png\" alt=\"\" /></div>\n\t<h5>Scroll to explore the chapters</h5>\n</div>\n\n<div class=\"content\">\n\t\n\t<div class=\"inner\">\n\t\t<ul class=\"history-sections\">\n\t\t\t{{ #sections }}\n\t\t\t\t<li>\n\t\t\t\t\t<a href=\"/#/history/{{ key }}\">\n\t\t\t\t\t\t<img src=\"{{ config.cdn }}images/fpo/{{ overviewImage }}\" alt=\"\" />\n\t\t\t\t\t</a>\t\n\t\t\t\t</li>\n\t\t\t{{ /sections }}\n\t\t</ul>\n\t</div>\n\n</div>\n\n<div class=\"title\">\n\t<p><span>Chapter 1:</span> <a href=\"/#/history\" class=\"btn\">The Early Years</a></p>\n</div>",
5915
5916	init: function( routeData, onComplete ) {
5917
5918		_data.config = Config;
5919
5920		var nav = $.select('.nav-controller');
5921		$.addClass('dark', nav);
5922
5923		this.render(_data);
5924		$.addClass('page', this.div);
5925
5926		this.sections = $.select('.grid-item', this.div);
5927		Velocity.hook(this.sections, "opacity", 0);
5928
5929		$.append(this.div, Stage);
5930
5931		this.wrapper = $.select('.history-sections', this.div);
5932		this.content = $.select('li', this.wrapper);
5933		this.title = $.select('.title', this.div);
5934
5935		this.renderer = new SnappyScroll( this.onRender.bind(this) );
5936		this.renderer.setWidth( 770 );
5937		this.renderer.setMaxIndex( this.content.length );
5938		this.renderer.onScrollUpdate = this.onScrollUpdate.bind(this);
5939
5940		this.addListeners();
5941		onComplete();
5942	},
5943
5944	addListeners: function() {
5945
5946		var _this = this;
5947
5948		$.on(this.div, 'click', function(e) {
5949
5950			var t = e.target.parentNode.parentNode; // ...
5951
5952			if( t !== _this.currentItem ) {
5953
5954				e.preventDefault();
5955
5956				var idx = _this.content.indexOf( t );
5957				_this.renderer.setIndex(idx);
5958			}
5959		});
5960	},
5961
5962	onRender: function( scr ) {
5963
5964		$.transform(this.wrapper, {
5965			x: scr
5966		});
5967
5968		for( var i = 0; i < this.content.length; i ++ ) {
5969
5970			var offset = this.content[ i ].offsetLeft;
5971			var position = offset + scr;
5972			var absPosition = Math.abs(position);
5973
5974			//- opacity
5975			var o = (( absPosition / 15 ) / 100);
5976				o = Util.clamp(o, 0, 1);
5977				o = 1 - o;
5978
5979			//- scale
5980			var s = (( absPosition / 50 ) / 100);
5981				s = Util.clamp(s, 0, 1);
5982				s = 1 - s;
5983
5984			$.css(this.content[ i ], {
5985				opacity: o
5986			}).transform(this.content[ i ], {
5987				scale: s
5988			});
5989		}
5990	},
5991
5992	onScrollUpdate: function( index ) {
5993
5994		if( index !== this.lastScroll ) {
5995
5996			var item = this.currentItem = this.content[ index ];
5997
5998			var d = _data.sections[ index ];
5999			var ch = 'Chapter ' + (parseInt(index) + 1) + ':';
6000
6001			var l = $.select('a', this.title);
6002			var p = $.select('span', this.title);
6003
6004			Shuffle(p, ch);
6005			Shuffle(l, d.title)
6006
6007			l[ 0 ].href = '#/history/' + d.key;
6008		}
6009
6010		this.lastScroll = index;
6011	},
6012
6013	animateOut: function( onComplete ) {
6014
6015		Velocity(this.div, {
6016			opacity: [ 0, 1 ]
6017		}, {
6018			duration: 1000,
6019			complete: onComplete
6020		});
6021
6022		Velocity(this.sections, "transition.fadeOut", {
6023			stagger: 500,
6024			duration: 1000,
6025			delay: 500
6026		});
6027
6028		this.renderer.stopRender();
6029	},
6030
6031	animateIn: function( onComplete ) {
6032
6033		var content = $.select('.inner', this.div);
6034		var bug = $.select('.scroll-bug');
6035		$.show(bug);
6036
6037		Velocity(this.div, {
6038			opacity: [ 1, 0 ]
6039		}, {
6040			duration: 1000,
6041			complete: onComplete,
6042			easing: 'linear'
6043		});
6044
6045		Velocity(this.sections, "transition.fadeIn", {
6046			stagger: 500,
6047			duration: 1000,
6048			delay: 500
6049		});
6050
6051		Velocity(content, {
6052			opacity: [ 1, 0 ],
6053			translateX: [ 0, -100 ]
6054		}, {
6055			duration: 1500,
6056			display: 'block',
6057			easing: 'easeOutCubic'
6058		});
6059
6060		Velocity(bug, {
6061			opacity: [ 1, 0 ]
6062		}, {
6063			duration: 500,
6064			easing: 'easeOutCubic'
6065		});
6066
6067		this.renderer.startRender();
6068	},
6069
6070	resize: function( w, h ) {
6071
6072		var wrapper = $.select('.history-sections', this.div);
6073		var max = Math.max(0, wrapper[0].scrollWidth - 770);
6074
6075		this.renderer.setLimits(-max, 0);
6076	}
6077});
6078
6079module.exports = HistoryView;
6080},{"./../Config":1,"./../Data":2,"./../components/DOM":6,"./../components/ShuffleLetters":18,"./../components/SnappyScroll":20,"./../components/Utils":22,"./../components/View":23,"./../components/oop/Class":28,"velocity-animate":54}],34:[function(require,module,exports){
6081
6082
6083var Device = require('./../components/Device');
6084var Class = require('./../components/oop/Class');
6085var View = require('./../components/View');
6086var Velocity = require('velocity-animate');
6087var $ = require('./../components/DOM');
6088var Config = require('./../Config');
6089
6090var HomeView = new Class({
6091
6092	name: "home-view",
6093	Extends: View,
6094	template: "\n<div class=\"content\">\n\t<div class=\"inner\">\n\n\t\t<div class=\"title icon\">\n\t\t\tThe Indelible History <img src=\"{{ config.cdn }}images/img-intro-icon.png\" alt=\"\" /> of The St. Louis Browns \n\t\t</div>\n\n\t\t<img src=\"{{ config.cdn }}images/home-text.png\" alt=\"\" class=\"title\" />\n\n\t\t<div class=\"title play-ball\">\n\t\t\t<a href=\"/#/history\">\n\t\t\t\t<span>Play Ball &rarr;</span>\n\t\t\t\t<span>Play Ball &rarr;</span>\n\t\t\t</a>\n\t\t</div>\n\n\t</div>\n</div>",
6095
6096	init: function( data, onComplete ) {
6097
6098		var _this = this;
6099		var nav = $.select('.nav-controller');
6100		$.removeClass(nav, 'dark');
6101
6102		data.config = Config;
6103
6104		this.render( data );
6105		$.addClass('page', this.div);
6106
6107		this.titles = $.select('.title', this.div);
6108
6109		Velocity.hook(this.titles, "opacity", 0);
6110
6111		if( !Device.system.touch ) {
6112
6113			var video = document.createElement('video');
6114			video.autoplay = true;
6115			video.loop = true;
6116
6117			video.src = Config.cdn + 'video/home-loop.' + Device.media.video;
6118
6119			$.css(video, {
6120				opacity: 0
6121			});
6122
6123			video.addEventListener('loadeddata', function(e) {
6124				
6125				_this.div.appendChild(video);
6126
6127				Velocity(video, {
6128					opacity: 1
6129				}, {
6130					duration: 500
6131				});
6132			});
6133			
6134		}
6135
6136		$.append(this.div, Stage);
6137		
6138		onComplete();
6139	},
6140
6141	animateIn: function( onComplete ) {
6142
6143		var content = $.select('.content .inner', this.div);
6144
6145		Velocity(this.div, {
6146			opacity: [ 1, 0 ],
6147			translateZ: 0
6148		}, {
6149			duration: 4000,
6150			complete: onComplete,
6151			easing: 'easeOutCubic'
6152		});
6153
6154		Velocity(this.titles, "transition.slideUpIn", {
6155			stagger: 400,
6156			duration: 1000,
6157			easing: 'easeOutCubic'
6158		});
6159
6160		Velocity(content, {
6161			rotateX: [ 0, 15 ]
6162		}, {
6163			duration: 1200,
6164			easing: 'easeOutCubic'
6165		});
6166
6167		setInterval(function() {
6168
6169			var x = (Math.random() * 6) - 3;
6170			var y = (Math.random() * 6) - 3;
6171
6172			Velocity(content, {
6173				blur: 3,
6174				translateX: x,
6175				translateY: y,
6176				translateZ: 0
6177			}, {
6178				duration: 10,
6179				loop: 1
6180			});
6181		}, 4000);
6182	},
6183
6184	animateOut: function( onComplete ) {
6185
6186		Velocity(this.div, {
6187			opacity: 0,
6188			translateZ: 0
6189		}, {
6190			duration: 2000,
6191			complete: onComplete,
6192			easing: 'easeOutCubic'
6193		});
6194
6195		Velocity(this.titles, "transition.slideDownOut", {
6196			stagger: 100,
6197			duration: 500,
6198			easing: 'easeOutCubic'
6199		});
6200
6201	},
6202
6203	resize: function( w, h ) {
6204
6205		// console.log(w, h);
6206	}
6207});
6208
6209module.exports = HomeView;
6210},{"./../Config":1,"./../components/DOM":6,"./../components/Device":7,"./../components/View":23,"./../components/oop/Class":28,"velocity-animate":54}],35:[function(require,module,exports){
6211
6212
6213var Class = require('./../components/oop/Class');
6214var View = require('./../components/View');
6215var Velocity = require('velocity-animate');
6216var Loop = require('raf-loop');
6217
6218var $ = require('./../components/DOM');
6219var Config = require('./../Config');
6220var VirtualScroll = require('./../components/VirtualScroll')();
6221var Util = require('./../components/Utils');
6222
6223var _ = require('underscore');
6224var _data = require('./../Data').players;
6225
6226var PlayersView = new Class({
6227
6228	name: "players-list-view",
6229	Extends: View,
6230	template: "<ol class=\"players-list\">\n\t{{#players}}\n\t\t<li>\n\t\t\t<a href=\"#\" data-href=\"{{ key }}\" class=\"btn info\">\n\t\t\t\t<span data-href=\"{{ key }}\" class=\"info\">{{{ firstName }}} {{{ lastName }}}</span>\n\t\t\t</a>\n\t\t</li>\n\t{{/players}}\n</ol>",
6231
6232	init: function( data, onComplete ) {
6233
6234		var sorted = _.sortBy(_data.players, "lastName");
6235		_data.players = sorted;
6236
6237		this.render(_data);
6238
6239		var content = $.select('.content', '.players-view');
6240		$.append(this.div, content);
6241
6242		this.list = $.select('li', this.div);
6243
6244		$.hide(this.div);
6245
6246		Velocity.hook(this.list, "opacity", 0);
6247	},
6248
6249	animateOut: function( newContent ) {
6250
6251		var _this = this;
6252
6253		Velocity(this.div, {
6254			opacity: 0
6255		}, {
6256			mobileHA: false,
6257			stagger: 100,
6258			duration: 250,
6259			display: 'none',
6260			complete: function() {
6261
6262				// _this.destroy();
6263				if( newContent && newContent.animateIn ) newContent.animateIn();
6264			}
6265		});
6266	},
6267
6268	animateIn: function( onComplete ) {
6269
6270		$.show(this.div);
6271
6272		Velocity(this.div, {
6273			opacity: 1
6274		}, {
6275			mobileHA: false,
6276			duration: 500
6277		});
6278
6279		Velocity(this.list, "transition.fadeIn", {
6280			stagger: 40,
6281			duration: 400,
6282			mobileHA: false
6283		});
6284	},
6285
6286	resize: function( w, h ) {
6287
6288		// console.log(w, h);
6289	}
6290});
6291
6292module.exports = PlayersView;
6293},{"./../Config":1,"./../Data":2,"./../components/DOM":6,"./../components/Utils":22,"./../components/View":23,"./../components/VirtualScroll":26,"./../components/oop/Class":28,"raf-loop":48,"underscore":53,"velocity-animate":54}],36:[function(require,module,exports){
6294
6295
6296var Class = require('./../components/oop/Class');
6297var View = require('./../components/View');
6298var Velocity = require('velocity-animate');
6299var Device = require('./../components/Device');
6300
6301var $ = require('./../components/DOM');
6302var Config = require('./../Config');
6303var Util = require('./../components/Utils');
6304var SmoothScroll = require('./../components/SmoothScroll');
6305var Config = require('./../Config');
6306
6307var _ = require('underscore');
6308var _data = require('./../Data').players;
6309
6310var lastCategory = "";
6311var isVisible = function(el) {
6312
6313    var rect = el.getBoundingClientRect();
6314    var threshold = 0.25;
6315
6316    return (
6317        rect.top <= (window.innerHeight * threshold) &&
6318        rect.bottom >= (window.innerHeight * threshold) &&
6319        rect.left >= -100 &&
6320        rect.right <= window.innerWidth
6321    );
6322};
6323
6324var PlayersPhotoView = new Class({
6325
6326	name: "players-photo-view",
6327	Extends: View,
6328	template: "<ol class=\"player-photos\">\n\t{{ #players }}
6328\n\t\t<li {{ #category }} data-category=\"{{ category }}\" {{ /category }}>\n\t\t\t<img src=\"{{ config.cdn }}images/players/{{ key }}.png\" alt=\"{{ name }}\" class=\"player\" />\n\t\t\t<div class=\"more-info\">\n\t\t\t\t{{ #hallOfFame }}\n\t\t\t\t\t<img src=\"{{ config.cdn }}images/hof-badge.png\" alt=\"\" class=\"badge\" />\n\t\t\t\t{{ /hallOfFame }}\n\t\t\t\t{{ #cardinalsPlayer }}\n\t\t\t\t\t<img src=\"{{ config.cdn }}images/cards-badge.png\" alt=\"\" class=\"badge\" />\n\t\t\t\t{{ /cardinalsPlayer }}\n\t\t\t\t<h2 class=\"info\" data-href=\"{{ key }}\">{{{ firstName }}} {{{ lastName }}}</h2>\n\t\t\t\t<a href=\"#\" data-href=\"{{ key }}\" class=\"btn info\">More Info</a>\n\t\t\t</div>\n\t\t</li>\n\t{{ /players }}\n</ol>\n\n<div class=\"alpha-controls\">\n\t<div class=\"grid\">\n\t\t<div class=\"indicator\"></div>\n\t\t<div data-category=\"a\" class=\"active\">A</div>\n\t\t<div data-category=\"b\">B</div>\n\t\t<div data-category=\"c\">C</div>\n\t\t<div data-category=\"d\">D</div>\n\t\t<div data-category=\"e\">E</div>\n\t\t<div data-category=\"f\">F</div>\n\t\t<div data-category=\"g\">G</div>\n\t\t<div data-category=\"h\">H</div>\n\t\t<div data-category=\"i\">I</div>\n\t\t<div data-category=\"j\">J</div>\n\t\t<div data-category=\"k\">K</div>\n\t\t<div data-category=\"l\">L</div>\n\t\t<div data-category=\"m\">M</div>\n\t\t<div data-category=\"n\">N</div>\n\t\t<div data-category=\"o\">O</div>\n\t\t<div data-category=\"p\">P</div>\n\t\t<div data-category=\"q\">Q</div>\n\t\t<div data-category=\"r\">R</div>\n\t\t<div data-category=\"s\">S</div>\n\t\t<div data-category=\"t\">T</div>\n\t\t<div data-category=\"u\">U</div>\n\t\t<div data-category=\"v\">V</div>\n\t\t<div data-category=\"w\">W</div>\n\t\t<div data-category=\"x\">X</div>\n\t\t<div data-category=\"y\">Y</div>\n\t\t<div data-category=\"z\">Z</div>\n\t</div>\n</div>",
6329
6330	init: function( data, onComplete ) {
6331
6332		var lastCategory;
6333
6334		_data.activeCategories = [];
6335
6336		var sorted = _.sortBy(_data.players, "lastName");
6337		var grouped = _.each(sorted, function( player ) { 
6338
6339			var category = player['lastName'].substr(0, 1).toLowerCase();
6340			
6341			if( category !== lastCategory ) {
6342
6343				player.category = category;
6344			    lastCategory = category;
6345
6346			    _data.activeCategories.push(category);
6347			}
6348		});
6349
6350		_data.players = grouped;
6351		_data.config = Config;
6352
6353		this.render(_data);
6354
6355		var content = $.select('.content', '.players-view');
6356		$.append(this.div, content);
6357
6358		this.controls = $.select('.alpha-controls', this.div);
6359		this.list = $.select('li', this.div);
6360		this.wrapper = $.select('.player-photos', this.div);
6361
6362		this.renderer = new SmoothScroll( this.onRender.bind(this), 0.0875 );
6363
6364		_.each(_data.activeCategories, function(e) {
6365
6366			var el = $.select('[data-category=' + e + ']', this.controls);
6367			$.addClass('selected', el);
6368		});
6369
6370		this.addListeners();
6371	},
6372
6373	addListeners: function() {
6374
6375		var _this = this;
6376		var controls = $.select('div', this.controls);
6377		var indicator = $.select('.indicator', this.controls);
6378
6379		$.on(this.controls[ 0 ], 'click', function(e) {
6380
6381			if( !$.hasClass(e.target, 'indicator') ) {
6382
6383				var category = e.target.innerHTML.toLowerCase();
6384				var target = $.select('.player-photos [data-category=' + category + ']', Stage)[ 0 ];
6385				
6386				if( target ) {
6387
6388					_this.renderer.easer.setTarget(-target.offsetLeft);
6389
6390					$.removeClass(controls, 'active');
6391					$.addClass('active', e.target);
6392
6393					var active = $.select('.active', _this.controls[ 0 ]);
6394					var offset = active[ 0 ].offsetLeft;
6395
6396					Velocity(indicator, {
6397						translateX: offset
6398					}, {
6399						duration: 500,
6400						easing: 'easeInOutCubic'
6401					});
6402				}
6403			}
6404		});
6405
6406		$.on(this.div, 'click', function(e) {
6407
6408			if( $.hasClass(e.target, 'player') ) {
6409
6410				var t = e.target.parentNode;
6411				var offset = t.offsetLeft * -1;
6412
6413				_this.renderer.setTarget(offset);
6414			}
6415		});
6416	},
6417
6418	onRender: function( scr ) {
6419
6420		$.transform(this.wrapper, {
6421			x: scr
6422		});
6423
6424		for( var i = 0; i < this.list.length; i ++ ) {
6425
6426			var offset = this.list[ i ].offsetLeft;
6427			var position = offset + scr;
6428			var absPosition = Math.abs(position);
6429			var category = $.attr(this.list[ i ], 'data-category');
6430			
6431			// get current letter in view
6432			if( category && category !== lastCategory && isVisible(this.list[ i ]) ) {
6433
6434				lastCategory = category;
6435				var controls = $.select('div', this.controls);
6436				var control = $.select('[data-category="' + category + '"]', this.controls);
6437				var offset = control[ 0 ].offsetLeft;
6438				var indicator = $.select('.indicator', this.controls);
6439				
6440				$.removeClass(controls, 'active');
6441				$.addClass('active', control);
6442
6443				Velocity(indicator, {
6444					translateX: offset
6445				}, {
6446					duration: 500,
6447					easing: 'easeOutCubic',
6448					queue: false
6449				});
6450			}
6451
6452			if( !Device.system.touch ) {
6453				//- opacity
6454				var o = (( absPosition / 8 ) / 100);
6455					o = Util.clamp(o, 0, 1);
6456					o = 1 - o;
6457
6458				//- x offset
6459				var tx = absPosition / 7;
6460					Util.clamp(tx, 0, 100);
6461
6462				$.transform(this.list[ i ], {
6463					x: tx
6464				});
6465
6466				$.css(this.list[ i ], {
6467					opacity: o
6468				});
6469			}
6470		}
6471	},
6472
6473	animateOut: function( newContent ) {
6474
6475		var _this = this;
6476
6477		Velocity(this.div, {
6478			opacity: 0,
6479			left: [ 100, 0 ]
6480		}, {
6481			duration: 750,
6482			easing: 'easeOutCubic',
6483			display: 'none',
6484			mobileHA: false,
6485			complete: function() {
6486
6487				if( newContent && newContent.animateIn ) newContent.animateIn();
6488			}
6489		});
6490
6491		// accomodate for whole div moving...
6492		Velocity(this.controls, {
6493			translateX: [ -100, 0 ],
6494			translateZ: 0
6495		}, {
6496			duration: 750,
6497			display: 'block',
6498			easing: 'easeOutCubic'
6499		});
6500
6501		var bug = $.select('.scroll-bug');
6502		
6503		Velocity(bug, {
6504			opacity: 0
6505		}, {
6506			duration: 500,
6507			easing: 'easeOutCubic'
6508		});
6509
6510		this.renderer.stopRender();
6511	},
6512
6513	animateIn: function( onComplete ) {
6514
6515		$.show(this.div);
6516
6517		this.renderer.startRender();
6518
6519		Velocity(this.div, {
6520			opacity: [ 1, 0 ],
6521			left: [ 0, -100 ]
6522		}, {
6523			duration: 1500,
6524			display: 'block',
6525			easing: 'easeOutCubic',
6526			mobileHA: false
6527		});
6528
6529		// accomodate for whole div moving...
6530		Velocity(this.controls, {
6531			translateX: [ 0, 100 ],
6532			translateZ: 0
6533		}, {
6534			duration: 1500,
6535			display: 'block',
6536			easing: 'easeOutCubic'
6537		});
6538
6539		var bug = $.select('.scroll-bug');
6540		Velocity.hook(bug, "opacity", 0);
6541		$.show(bug);
6542
6543		Velocity(bug, {
6544			opacity: 1
6545		}, {
6546			duration: 500,
6547			easing: 'easeOutCubic'
6548		});
6549	},
6550
6551	resize: function( w, h ) {
6552
6553		var wrapper = $.select('.player-photos', this.div);
6554		var max = Math.max(0, ( wrapper[0].scrollWidth - (window.innerWidth - 400) ));
6555
6556		this.renderer.setLimits((max * -1), 0);
6557	}
6558});
6559
6560module.exports = PlayersPhotoView;
6561},{"./../Config":1,"./../Data":2,"./../components/DOM":6,"./../components/Device":7,"./../components/SmoothScroll":19,"./../components/Utils":22,"./../components/View":23,"./../components/oop/Class":28,"underscore":53,"velocity-animate":54}],37:[function(require,module,exports){
6562
6563
6564var Class = require('./../components/oop/Class');
6565var View = require('./../components/View');
6566var Velocity = require('velocity-animate');
6567
6568var ListView = require('./PlayersListView');
6569var PhotoView = require('./PlayersPhotoView');
6570var Overlay = require('./../components/Overlay');
6571
6572var $ = require('./../components/DOM');
6573var Config = require('./../Config');
6574var VirtualScroll = require('./../components/VirtualScroll')();
6575var Util = require('./../components/Utils');
6576
6577var _ = require('underscore');
6578var _data = require('./../Data').players;
6579
6580
6581var PlayersView = new Class({
6582
6583	name: "players-view",
6584	Extends: View,
6585	template: "<div class=\"page-title\">\n\t<h1>{{ title}}</h1>\n</div>\n\n<div class=\"scroll-bug\" style=\"display: none;\">\n\t<div><img src=\"{{ config.cdn }}images/bg/icn-right-arrow.png\" alt=\"\" /></div>\n\t<h5>Scroll to explore notable and living browns players</h5>\n</div>\n\n<div class=\"content\"></div>\n\n<div class=\"controls\">\n\t<ul>\n\t\t<li class=\"explore active\">Explore</li>\n\t\t<li class=\"list\">List</li>\n\t</ul>\n</div>",
6586	overlay: new Overlay(),
6587
6588	init: function( data, onComplete ) {
6589
6590		var nav = $.select('.nav-controller');
6591		$.addClass('dark', nav);
6592
6593		_data.config = Config;
6594
6595		this.data = _data;
6596
6597		this.render(this.data);
6598		$.addClass('page', this.div);
6599
6600		$.append(this.div, Stage);
6601
6602		//- initialize separate views
6603		this.photoView = new PhotoView();
6604		this.listView = new ListView();
6605
6606		this.listView.init();
6607		this.photoView.init();
6608
6609		this.overlay.init( this );
6610		this.currentView = this.photoView;
6611
6612		this.addListeners();
6613		onComplete();
6614	},
6615
6616	addListeners: function() {
6617
6618		var _this = this;
6619		var controls = $.select('.controls', this.div);
6620		var controlItems = $.select('li', controls);
6621
6622		$.on(controls[ 0 ], 'click', function(e) {
6623
6624			if( $.hasClass(e.target, 'list') ) {
6625
6626				$.removeClass(controlItems, 'active');
6627				_this.swap(_this.listView);
6628				_this.currentView = _this.listView;
6629				$.addClass('active', controlItems[ 1 ]);
6630			} else if( $.hasClass(e.target, 'explore') ) {
6631
6632				$.removeClass(controlItems, 'active');
6633				_this.swap(_this.photoView);
6634				_this.currentView = _this.photoView;
6635				$.addClass('active', controlItems[ 0 ]);
6636			}
6637		});
6638
6639		$.on(this.div, 'click', function(e) {
6640
6641			var attr = $.attr(e.target, 'data-href');
6642			var btn = $.hasClass(e.target, 'info');
6643			var overlay = e.target.className == 'close';
6644
6645			if( attr && btn ) {
6646
6647				e.preventDefault();
6648				e.stopPropagation();
6649
6650				var player = _.findWhere(_data.players, { "key": attr });
6651				_this.showOverlay( player );
6652			} else if( overlay ) {
6653
6654				e.preventDefault();
6655				_this.hideOverlay();
6656			}
6657		});
6658	},
6659
6660	swap: function( newContent ) {
6661
6662		this.currentView.animateOut(newContent);
6663	},
6664
6665	animateOut: function( onComplete ) {
6666
6667		Velocity(this.div, {
6668			opacity: [ 0, 1 ]
6669		}, {
6670			duration: 1000,
6671			complete: onComplete
6672		});
6673
6674		this.currentView.animateOut();
6675	},
6676
6677	animateIn: function( onComplete ) {
6678
6679		Velocity(this.div, {
6680			opacity: [ 1, 0 ]
6681		}, {
6682			duration: 1000,
6683			complete: onComplete,
6684			easing: 'linear'
6685		});
6686
6687		this.currentView.animateIn();
6688	},
6689
6690	showOverlay: function( playerData ) {
6691
6692		this.overlay.populate( playerData, "players" );
6693
6694		Velocity(this.currentView.div, {
6695			opacity: [ 0.5, 1 ]
6696		}, {
6697			duration: 1500,
6698			easing: 'easeOutCubic',
6699			mobileHA: false
6700		});
6701
6702		if( this.currentView == this.photoView ) {
6703
6704			this.photoView.renderer.stopRender();
6705		}	
6706	},
6707
6708	hideOverlay: function() {
6709
6710		Velocity(this.currentView.div, {
6711			opacity: [ 1, 0.5 ]
6712		}, {
6713			duration: 500,
6714			easing: 'easeOutCubic',
6715			mobileHA: false
6716		});
6717
6718		this.overlay.animateOut();
6719
6720		if( this.currentView == this.photoView ) {
6721
6722			this.photoView.renderer.startRender();
6723		}
6724	},
6725
6726	resize: function( w, h ) {
6727
6728		this.photoView.resize( w, h );
6729		this.overlay.resize( w, h );
6730	}
6731});
6732
6733module.exports = PlayersView;
6734},{"./../Config":1,"./../Data":2,"./../components/DOM":6,"./../components/Overlay":15,"./../components/Utils":22,"./../components/View":23,"./../components/VirtualScroll":26,"./../components/oop/Class":28,"./PlayersListView":35,"./PlayersPhotoView":36,"underscore":53,"velocity-animate":54}],38:[function(require,module,exports){
6735
6736
6737var Class = require('./../components/oop/Class');
6738var View = require('./../components/View');
6739var Velocity = require('velocity-animate');
6740var $ = require('./../components/DOM');
6741var Config = require('./../Config');
6742
6743var Preloader = require('./../components/PreLoader');
6744var Ticker = require('./../components/Ticker');
6745
6746var Images = require('./../components/Bundle');
6747var ImagesContainer = $.select('#image-store')[ 0 ];
6748
6749var PreloaderView = new Class({
6750
6751	name: "preloader",
6752	Extends: View,
6753	template: "<div class=\"content\">\n\t<img src=\"{{ config.cdn }}images/bg/loading.gif\" alt=\"\" />\n\t<div class=\"progress\"></div>\n</div>",
6754
6755	initialize: function( onComplete ) {
6756
6757		var _this = this;
6758		var data = {
6759			config: Config
6760		};
6761
6762		this.onPreloadComplete = onComplete;
6763
6764		this.loader = new Preloader(Images, {
6765			pipeline: true,
6766			onProgress: _this.onProgress.bind(this),
6767			onComplete: _this.onComplete.bind(this)
6768		});
6769
6770		this.render(data, document.body);
6771
6772		this.progress = $.select('.progress', this.div)[ 0 ];
6773	},
6774
6775	animateIn: function( onComplete ) {
6776
6777		
6778	},
6779
6780	animateOut: function( onComplete ) {
6781
6782		Velocity(this.div, {
6783			opacity: 0
6784		}, {
6785			display: 'none',
6786			duration: 1200,
6787			complete: onComplete
6788		});
6789	},
6790
6791	onProgress: function( img, imageEl, index ) {
6792
6793		// fires every time an image is done or errors. 
6794		// imageEl will be falsy if error
6795		// console.log('just ' +  (!imageEl ? 'failed: ' : 'loaded: ') + img);
6796
6797		ImagesContainer.appendChild( imageEl );
6798		
6799		var percent = Math.floor((100 / this.loader.queue.length) * this.loader.completed.length);
6800
6801		this.progress.innerHTML = percent + '%';
6802	},
6803
6804	onComplete: function( loaded, errors ) {
6805
6806		// fires when whole list is done. cache is primed.
6807		// console.log('done', loaded);
6808
6809		ImagesContainer.parentNode.removeChild( ImagesContainer );
6810		
6811		if ( errors ) {
6812			console.log('the following failed', errors);
6813		}
6814
6815		this.onPreloadComplete();
6816	},
6817
6818	destroy: function() {
6819
6820		document.body.removeChild(this.div);
6821	}
6822});
6823
6824module.exports = PreloaderView;
6825},{"./../Config":1,"./../components/Bundle":4,"./../components/DOM":6,"./../components/PreLoader":16,"./../components/Ticker":21,"./../components/View":23,"./../components/oop/Class":28,"velocity-animate":54}],39:[function(require,module,exports){
6826
6827
6828var Class = require('./../components/oop/Class');
6829var View = require('./../components/View');
6830var Velocity = require('velocity-animate');
6831var $ = require('./../components/DOM');
6832
6833var StoreView = new Class({
6834
6835	name: "store-view",
6836	Extends: View,
6837	template: "<div class=\"page-title\">\n\t<h1>Store</h1>\n</div>",
6838
6839	init: function( data, onComplete ) {
6840
6841		var nav = $.select('.nav-controller');
6842		$.addClass('dark', nav);
6843
6844		var stage = document.querySelector('#stage');		
6845		this.render(data, stage);
6846		$.addClass('page', this.div);
6847
6848		onComplete();
6849	},
6850
6851	animateOut: function( onComplete ) {
6852
6853		Velocity(this.div, {
6854			opacity: [ 0, 1 ]
6855		}, {
6856			duration: 1000,
6857			complete: onComplete
6858		});
6859	},
6860
6861	animateIn: function( onComplete ) {
6862
6863		Velocity(this.div, {
6864			opacity: [ 1, 0 ]
6865		}, {
6866			duration: 1000,
6867			complete: onComplete,
6868			easing: 'linear'
6869		});
6870	},
6871
6872	resize: function( w, h ) {
6873
6874		// console.log(w, h);
6875	}
6876});
6877
6878module.exports = StoreView;
6879},{"./../components/DOM":6,"./../components/View":23,"./../components/oop/Class":28,"velocity-animate":54}],40:[function(require,module,exports){
6880var Framework = require('./app/components/Application');
6881var $ = require('./app/components/DOM');
6882
6883var PreLoader = require('./app/views/PreloaderView');
6884var Nav = require('./app/components/Nav');
6885var HomeView = require('./app/views/HomeView');
6886var HistoryView = require('./app/views/HistoryView');
6887var HistorySectionView = require('./app/views/HistorySectionView');
6888var PlayersView = require('./app/views/PlayersView');
6889var StoreView = require('./app/views/StoreView');
6890var BlogPostView = require('./app/views/BlogPostView');
6891var ContactView = require('./app/views/ContactView');
6892var GenericView = require('./app/views/GenericView');
6893
6894var Device = require('./app/components/Device');
6895
6896(function() {
6897
6898	var nav = new Nav();
6899
6900	var app = Framework({
6901		autoResize: true,
6902		overlap: !Device.system.touch,
6903		initSection: PreLoader,
6904		onRoute: nav.animateOut.bind( nav ),
6905		routes: {
6906			'/': HomeView,
6907			'/history': HistoryView,
6908			'/history/:id': HistorySectionView,
6909			'/players': PlayersView,
6910			'/about': GenericView,
6911			'/membership': GenericView,
6912			'/store': StoreView,
6913			'/news-and-events': GenericView,
6914			'/news-and-events/:id': BlogPostView,
6915			'/contact': GenericView
6916		}
6917	});
6918
6919	//- kickitoff
6920	var exp = window && Device.system.pushstate && window.innerWidth > 767;
6921
6922	if( exp ) {
6923
6924		window.Stage = $.select('#stage')[ 0 ];
6925		app.init();
6926
6927		if( Device.system.touch ) {
6928
6929			document.addEventListener('touchmove', function(e) {
6930
6931				e.preventDefault();
6932			});
6933		}
6934	} else {
6935
6936		window.location = '/fallback';
6937	}
6938})();
6939},{"./app/components/Application":3,"./app/components/DOM":6,"./app/components/Device":7,"./app/components/Nav":13,"./app/views/BlogPostView":29,"./app/views/ContactView":30,"./app/views/GenericView":31,"./app/views/HistorySectionView":32,"./app/views/HistoryView":33,"./app/views/HomeView":34,"./app/views/PlayersView":37,"./app/views/PreloaderView":38,"./app/views/StoreView":39}],41:[function(require,module,exports){
6940/*!
6941  * Bonzo: DOM Utility (c) Dustin Diaz 2012
6942  * https://github.com/ded/bonzo
6943  * License MIT
6944  */
6945(function (name, context, definition) {
6946  if (typeof module != 'undefined' && module.exports) module.exports = definition()
6947  else if (typeof define == 'function' && define.amd) define(definition)
6948  else context[name] = definition()
6949}
6949)('bonzo', this, function() {
6950  var win = window
6951    , doc = win.document
6952    , html = doc.documentElement
6953    , parentNode = 'parentNode'
6954    , specialAttributes = /^(checked|value|selected|disabled)$/i
6955      // tags that we have trouble inserting *into*
6956    , specialTags = /^(select|fieldset|table|tbody|tfoot|td|tr|colgroup)$/i
6957    , simpleScriptTagRe = /\s*<script +src=['"]([^'"]+)['"]>/
6958    , table = ['<table>', '</table>', 1]
6959    , td = ['<table><tbody><tr>', '</tr></tbody></table>', 3]
6960    , option = ['<select>', '</select>', 1]
6961    , noscope = ['_', '', 0, 1]
6962    , tagMap = { // tags that we have trouble *inserting*
6963          thead: table, tbody: table, tfoot: table, colgroup: table, caption: table
6964        , tr: ['<table><tbody>', '</tbody></table>', 2]
6965        , th: td , td: td
6966        , col: ['<table><colgroup>', '</colgroup></table>', 2]
6967        , fieldset: ['<form>', '</form>', 1]
6968        , legend: ['<form><fieldset>', '</fieldset></form>', 2]
6969        , option: option, optgroup: option
6970        , script: noscope, style: noscope, link: noscope, param: noscope, base: noscope
6971      }
6972    , stateAttributes = /^(checked|selected|disabled)$/
6973    , hasClass, addClass, removeClass
6974    , uidMap = {}
6975    , uuids = 0
6976    , digit = /^-?[\d\.]+$/
6977    , dattr = /^data-(.+)$/
6978    , px = 'px'
6979    , setAttribute = 'setAttribute'
6980    , getAttribute = 'getAttribute'
6981    , features = function() {
6982        var e = doc.createElement('p')
6983        return {
6984          transform: function () {
6985            var props = ['transform', 'webkitTransform', 'MozTransform', 'OTransform', 'msTransform'], i
6986            for (i = 0; i < props.length; i++) {
6987              if (props[i] in e.style) return props[i]
6988            }
6989          }()
6990        , classList: 'classList' in e
6991        }
6992      }()
6993    , whitespaceRegex = /\s+/
6994    , toString = String.prototype.toString
6995    , unitless = { lineHeight: 1, zoom: 1, zIndex: 1, opacity: 1, boxFlex: 1, WebkitBoxFlex: 1, MozBoxFlex: 1 }
6996    , query = doc.querySelectorAll && function (selector) { return doc.querySelectorAll(selector) }
6997
6998
6999  function getStyle(el, property) {
7000    var value = null
7001      , computed = doc.defaultView.getComputedStyle(el, '')
7002    computed && (value = computed[property])
7003    return el.style[property] || value
7004  }
7005
7006
7007  function isNode(node) {
7008    return node && node.nodeName && (node.nodeType == 1 || node.nodeType == 11)
7009  }
7010
7011
7012  function normalize(node, host, clone) {
7013    var i, l, ret
7014    if (typeof node == 'string') return bonzo.create(node)
7015    if (isNode(node)) node = [ node ]
7016    if (clone) {
7017      ret = [] // don't change original array
7018      for (i = 0, l = node.length; i < l; i++) ret[i] = cloneNode(host, node[i])
7019      return ret
7020    }
7021    return node
7022  }
7023
7024  /**
7025   * @param {string} c a class name to test
7026   * @return {boolean}
7027   */
7028  function classReg(c) {
7029    return new RegExp('(^|\\s+)' + c + '(\\s+|$)')
7030  }
7031
7032
7033  /**
7034   * @param {Bonzo|Array} ar
7035   * @param {function(Object, number, (Bonzo|Array))} fn
7036   * @param {Object=} opt_scope
7037   * @param {boolean=} opt_rev
7038   * @return {Bonzo|Array}
7039   */
7040  function each(ar, fn, opt_scope, opt_rev) {
7041    var ind, i = 0, l = ar.length
7042    for (; i < l; i++) {
7043      ind = opt_rev ? ar.length - i - 1 : i
7044      fn.call(opt_scope || ar[ind], ar[ind], ind, ar)
7045    }
7046    return ar
7047  }
7048
7049
7050  /**
7051   * @param {Bonzo|Array} ar
7052   * @param {function(Object, number, (Bonzo|Array))} fn
7053   * @param {Object=} opt_scope
7054   * @return {Bonzo|Array}
7055   */
7056  function deepEach(ar, fn, opt_scope) {
7057    for (var i = 0, l = ar.length; i < l; i++) {
7058      if (isNode(ar[i])) {
7059        deepEach(ar[i].childNodes, fn, opt_scope)
7060        fn.call(opt_scope || ar[i], ar[i], i, ar)
7061      }
7062    }
7063    return ar
7064  }
7065
7066
7067  /**
7068   * @param {string} s
7069   * @return {string}
7070   */
7071  function camelize(s) {
7072    return s.replace(/-(.)/g, function (m, m1) {
7073      return m1.toUpperCase()
7074    })
7075  }
7076
7077
7078  /**
7079   * @param {string} s
7080   * @return {string}
7081   */
7082  function decamelize(s) {
7083    return s ? s.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() : s
7084  }
7085
7086
7087  /**
7088   * @param {Element} el
7089   * @return {*}
7090   */
7091  function data(el) {
7092    el[getAttribute]('data-node-uid') || el[setAttribute]('data-node-uid', ++uuids)
7093    var uid = el[getAttribute]('data-node-uid')
7094    return uidMap[uid] || (uidMap[uid] = {})
7095  }
7096
7097
7098  /**
7099   * removes the data associated with an element
7100   * @param {Element} el
7101   */
7102  function clearData(el) {
7103    var uid = el[getAttribute]('data-node-uid')
7104    if (uid) delete uidMap[uid]
7105  }
7106
7107
7108  function dataValue(d) {
7109    var f
7110    try {
7111      return (d === null || d === undefined) ? undefined :
7112        d === 'true' ? true :
7113          d === 'false' ? false :
7114            d === 'null' ? null :
7115              (f = parseFloat(d)) == d ? f : d;
7116    } catch(e) {}
7117    return undefined
7118  }
7119
7120
7121  /**
7122   * @param {Bonzo|Array} ar
7123   * @param {function(Object, number, (Bonzo|Array))} fn
7124   * @param {Object=} opt_scope
7125   * @return {boolean} whether `some`thing was found
7126   */
7127  function some(ar, fn, opt_scope) {
7128    for (var i = 0, j = ar.length; i < j; ++i) if (fn.call(opt_scope || null, ar[i], i, ar)) return true
7129    return false
7130  }
7131
7132
7133  /**
7134   * this could be a giant enum of CSS properties
7135   * but in favor of file size sans-closure deadcode optimizations
7136   * we're just asking for any ol string
7137   * then it gets transformed into the appropriate style property for JS access
7138   * @param {string} p
7139   * @return {string}
7140   */
7141  function styleProperty(p) {
7142      (p == 'transform' && (p = features.transform)) ||
7143        (/^transform-?[Oo]rigin$/.test(p) && (p = features.transform + 'Origin'))
7144      return p ? camelize(p) : null
7145  }
7146
7147  // this insert method is intense
7148  function insert(target, host, fn, rev) {
7149    var i = 0, self = host || this, r = []
7150      // target nodes could be a css selector if it's a string and a selector engine is present
7151      // otherwise, just use target
7152      , nodes = query && typeof target == 'string' && target.charAt(0) != '<' ? query(target) : target
7153    // normalize each node in case it's still a string and we need to create nodes on the fly
7154    each(normalize(nodes), function (t, j) {
7155      each(self, function (el) {
7156        fn(t, r[i++] = j > 0 ? cloneNode(self, el) : el)
7157      }, null, rev)
7158    }, this, rev)
7159    self.length = i
7160    each(r, function (e) {
7161      self[--i] = e
7162    }, null, !rev)
7163    return self
7164  }
7165
7166
7167  /**
7168   * sets an element to an explicit x/y position on the page
7169   * @param {Element} el
7170   * @param {?number} x
7171   * @param {?number} y
7172   */
7173  function xy(el, x, y) {
7174    var $el = bonzo(el)
7175      , style = $el.css('position')
7176      , offset = $el.offset()
7177      , rel = 'relative'
7178      , isRel = style == rel
7179      , delta = [parseInt($el.css('left'), 10), parseInt($el.css('top'), 10)]
7180
7181    if (style == 'static') {
7182      $el.css('position', rel)
7183      style = rel
7184    }
7185
7186    isNaN(delta[0]) && (delta[0] = isRel ? 0 : el.offsetLeft)
7187    isNaN(delta[1]) && (delta[1] = isRel ? 0 : el.offsetTop)
7188
7189    x != null && (el.style.left = x - offset.left + delta[0] + px)
7190    y != null && (el.style.top = y - offset.top + delta[1] + px)
7191
7192  }
7193
7194  // classList support for class management
7195  // altho to be fair, the api sucks because it won't accept multiple classes at once
7196  if (features.classList) {
7197    hasClass = function (el, c) {
7198      return el.classList.contains(c)
7199    }
7200    addClass = function (el, c) {
7201      el.classList.add(c)
7202    }
7203    removeClass = function (el, c) {
7204      el.classList.remove(c)
7205    }
7206  }
7207  else {
7208    hasClass = function (el, c) {
7209      return classReg(c).test(el.className)
7210    }
7211    addClass = function (el, c) {
7212      el.className = (el.className + ' ' + c).trim()
7213    }
7214    removeClass = function (el, c) {
7215      el.className = (el.className.replace(classReg(c), ' ')).trim()
7216    }
7217  }
7218
7219
7220  /**
7221   * this allows method calling for setting values
7222   *
7223   * @example
7224   * bonzo(elements).css('color', function (el) {
7225   *   return el.getAttribute('data-original-color')
7226   * })
7227   *
7228   * @param {Element} el
7229   * @param {function (Element)|string} v
7230   * @return {string}
7231   */
7232  function setter(el, v) {
7233    return typeof v == 'function' ? v.call(el, el) : v
7234  }
7235
7236  function scroll(x, y, type) {
7237    var el = this[0]
7238    if (!el) return this
7239    if (x == null && y == null) {
7240      return (isBody(el) ? getWindowScroll() : { x: el.scrollLeft, y: el.scrollTop })[type]
7241    }
7242    if (isBody(el)) {
7243      win.scrollTo(x, y)
7244    } else {
7245      x != null && (el.scrollLeft = x)
7246      y != null && (el.scrollTop = y)
7247    }
7248    return this
7249  }
7250
7251  /**
7252   * @constructor
7253   * @param {Array.<Element>|Element|Node|string} elements
7254   */
7255  function Bonzo(elements) {
7256    this.length = 0
7257    if (elements) {
7258      elements = typeof elements !== 'string' &&
7259        !elements.nodeType &&
7260        typeof elements.length !== 'undefined' ?
7261          elements :
7262          [elements]
7263      this.length = elements.length
7264      for (var i = 0; i < elements.length; i++) this[i] = elements[i]
7265    }
7266  }
7267
7268  Bonzo.prototype = {
7269
7270      /**
7271       * @param {number} index
7272       * @return {Element|Node}
7273       */
7274      get: function (index) {
7275        return this[index] || null
7276      }
7277
7278      // itetators
7279      /**
7280       * @param {function(Element|Node)} fn
7281       * @param {Object=} opt_scope
7282       * @return {Bonzo}
7283       */
7284    , each: function (fn, opt_scope) {
7285        return each(this, fn, opt_scope)
7286      }
7287
7288      /**
7289       * @param {Function} fn
7290       * @param {Object=} opt_scope
7291       * @return {Bonzo}
7292       */
7293    , deepEach: function (fn, opt_scope) {
7294        return deepEach(this, fn, opt_scope)
7295      }
7296
7297
7298      /**
7299       * @param {Function} fn
7300       * @param {Function=} opt_reject
7301       * @return {Array}
7302       */
7303    , map: function (fn, opt_reject) {
7304        var m = [], n, i
7305        for (i = 0; i < this.length; i++) {
7306          n = fn.call(this, this[i], i)
7307          opt_reject ? (opt_reject(n) && m.push(n)) : m.push(n)
7308        }
7309        return m
7310      }
7311
7312    // text and html inserters!
7313
7314    /**
7315     * @param {string} h the HTML to insert
7316     * @param {boolean=} opt_text whether to set or get text content
7317     * @return {Bonzo|string}
7318     */
7319    , html: function (h, opt_text) {
7320        var method = opt_text
7321              ? 'textContent'
7322              : 'innerHTML'
7323          , that = this
7324          , append = function (el, i) {
7325              each(normalize(h, that, i), function (node) {
7326                el.appendChild(node)
7327              })
7328            }
7329          , updateElement = function (el, i) {
7330              try {
7331                if (opt_text || (typeof h == 'string' && !specialTags.test(el.tagName))) {
7332                  return el[method] = h
7333                }
7334              } catch (e) {}
7335              append(el, i)
7336            }
7337        return typeof h != 'undefined'
7338          ? this.empty().each(updateElement)
7339          : this[0] ? this[0][method] : ''
7340      }
7341
7342      /**
7343       * @param {string=} opt_text the text to set, otherwise this is a getter
7344       * @return {Bonzo|string}
7345       */
7346    , text: function (opt_text) {
7347        return this.html(opt_text, true)
7348      }
7349
7350      // more related insertion methods
7351
7352      /**
7353       * @param {Bonzo|string|Element|Array} node
7354       * @return {Bonzo}
7355       */
7356    , append: function (node) {
7357        var that = this
7358        return this.each(function (el, i) {
7359          each(normalize(node, that, i), function (i) {
7360            el.appendChild(i)
7361          })
7362        })
7363      }
7364
7365
7366      /**
7367       * @param {Bonzo|string|Element|Array} node
7368       * @return {Bonzo}
7369       */
7370    , prepend: function (node) {
7371        var that = this
7372        return this.each(function (el, i) {
7373          var first = el.firstChild
7374          each(normalize(node, that, i), function (i) {
7375            el.insertBefore(i, first)
7376          })
7377        })
7378      }
7379
7380
7381      /**
7382       * @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
7383       * @param {Object=} opt_host an optional host scope (primarily used when integrated 
7383with Ender)
7384       * @return {Bonzo}
7385       */
7386    , appendTo: function (target, opt_host) {
7387        return insert.call(this, target, opt_host, function (t, el) {
7388          t.appendChild(el)
7389        })
7390      }
7391
7392
7393      /**
7394       * @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
7395       * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
7396       * @return {Bonzo}
7397       */
7398    , prependTo: function (target, opt_host) {
7399        return insert.call(this, target, opt_host, function (t, el) {
7400          t.insertBefore(el, t.firstChild)
7401        }, 1)
7402      }
7403
7404
7405      /**
7406       * @param {Bonzo|string|Element|Array} node
7407       * @return {Bonzo}
7408       */
7409    , before: function (node) {
7410        var that = this
7411        return this.each(function (el, i) {
7412          each(normalize(node, that, i), function (i) {
7413            el[parentNode].insertBefore(i, el)
7414          })
7415        })
7416      }
7417
7418
7419      /**
7420       * @param {Bonzo|string|Element|Array} node
7421       * @return {Bonzo}
7422       */
7423    , after: function (node) {
7424        var that = this
7425        return this.each(function (el, i) {
7426          each(normalize(node, that, i), function (i) {
7427            el[parentNode].insertBefore(i, el.nextSibling)
7428          }, null, 1)
7429        })
7430      }
7431
7432
7433      /**
7434       * @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
7435       * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
7436       * @return {Bonzo}
7437       */
7438    , insertBefore: function (target, opt_host) {
7439        return insert.call(this, target, opt_host, function (t, el) {
7440          t[parentNode].insertBefore(el, t)
7441        })
7442      }
7443
7444
7445      /**
7446       * @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
7447       * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
7448       * @return {Bonzo}
7449       */
7450    , insertAfter: function (target, opt_host) {
7451        return insert.call(this, target, opt_host, function (t, el) {
7452          var sibling = t.nextSibling
7453          sibling ?
7454            t[parentNode].insertBefore(el, sibling) :
7455            t[parentNode].appendChild(el)
7456        }, 1)
7457      }
7458
7459
7460      /**
7461       * @param {Bonzo|string|Element|Array} node
7462       * @return {Bonzo}
7463       */
7464    , replaceWith: function (node) {
7465        var that = this
7466        return this.each(function (el, i) {
7467          each(normalize(node, that, i), function (i) {
7468            el[parentNode] && el[parentNode].replaceChild(i, el)
7469          })
7470        })
7471      }
7472
7473      /**
7474       * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
7475       * @return {Bonzo}
7476       */
7477    , clone: function (opt_host) {
7478        var ret = [] // don't change original array
7479          , l, i
7480        for (i = 0, l = this.length; i < l; i++) ret[i] = cloneNode(opt_host || this, this[i])
7481        return bonzo(ret)
7482      }
7483
7484      // class management
7485
7486      /**
7487       * @param {string} c
7488       * @return {Bonzo}
7489       */
7490    , addClass: function (c) {
7491        c = toString.call(c).split(whitespaceRegex)
7492        return this.each(function (el) {
7493          // we `each` here so you can do $el.addClass('foo bar')
7494          each(c, function (c) {
7495            if (c && !hasClass(el, setter(el, c)))
7496              addClass(el, setter(el, c))
7497          })
7498        })
7499      }
7500
7501
7502      /**
7503       * @param {string} c
7504       * @return {Bonzo}
7505       */
7506    , removeClass: function (c) {
7507        c = toString.call(c).split(whitespaceRegex)
7508        return this.each(function (el) {
7509          each(c, function (c) {
7510            if (c && hasClass(el, setter(el, c)))
7511              removeClass(el, setter(el, c))
7512          })
7513        })
7514      }
7515
7516
7517      /**
7518       * @param {string} c
7519       * @return {boolean}
7520       */
7521    , hasClass: function (c) {
7522        c = toString.call(c).split(whitespaceRegex)
7523        return some(this, function (el) {
7524          return some(c, function (c) {
7525            return c && hasClass(el, c)
7526          })
7527        })
7528      }
7529
7530
7531      /**
7532       * @param {string} c classname to toggle
7533       * @param {boolean=} opt_condition whether to add or remove the class straight away
7534       * @return {Bonzo}
7535       */
7536    , toggleClass: function (c, opt_condition) {
7537        c = toString.call(c).split(whitespaceRegex)
7538        return this.each(function (el) {
7539          each(c, function (c) {
7540            if (c) {
7541              typeof opt_condition !== 'undefined' ?
7542                opt_condition ? !hasClass(el, c) && addClass(el, c) : removeClass(el, c) :
7543                hasClass(el, c) ? removeClass(el, c) : addClass(el, c)
7544            }
7545          })
7546        })
7547      }
7548
7549      // display togglers
7550
7551      /**
7552       * @param {string=} opt_type useful to set back to anything other than an empty string
7553       * @return {Bonzo}
7554       */
7555    , show: function (opt_type) {
7556        opt_type = typeof opt_type == 'string' ? opt_type : ''
7557        return this.each(function (el) {
7558          el.style.display = opt_type
7559        })
7560      }
7561
7562
7563      /**
7564       * @return {Bonzo}
7565       */
7566    , hide: function () {
7567        return this.each(function (el) {
7568          el.style.display = 'none'
7569        })
7570      }
7571
7572
7573      /**
7574       * @param {Function=} opt_callback
7575       * @param {string=} opt_type
7576       * @return {Bonzo}
7577       */
7578    , toggle: function (opt_callback, opt_type) {
7579        opt_type = typeof opt_type == 'string' ? opt_type : '';
7580        typeof opt_callback != 'function' && (opt_callback = null)
7581        return this.each(function (el) {
7582          el.style.display = (el.offsetWidth || el.offsetHeight) ? 'none' : opt_type;
7583          opt_callback && opt_callback.call(el)
7584        })
7585      }
7586
7587
7588      // DOM Walkers & getters
7589
7590      /**
7591       * @return {Element|Node}
7592       */
7593    , first: function () {
7594        return bonzo(this.length ? this[0] : [])
7595      }
7596
7597
7598      /**
7599       * @return {Element|Node}
7600       */
7601    , last: function () {
7602        return bonzo(this.length ? this[this.length - 1] : [])
7603      }
7604
7605
7606      /**
7607       * @return {Element|Node}
7608       */
7609    , next: function () {
7610        return this.related('nextSibling')
7611      }
7612
7613
7614      /**
7615       * @return {Element|Node}
7616       */
7617    , previous: function () {
7618        return this.related('previousSibling')
7619      }
7620
7621
7622      /**
7623       * @return {Element|Node}
7624       */
7625    , parent: function() {
7626        return this.related(parentNode)
7627      }
7628
7629
7630      /**
7631       * @private
7632       * @param {string} method the directional DOM method
7633       * @return {Element|Node}
7634       */
7635    , related: function (method) {
7636        return bonzo(this.map(
7637          function (el) {
7638            el = el[method]
7639            while (el && el.nodeType !== 1) {
7640              el = el[method]
7641            }
7642            return el || 0
7643          },
7644          function (el) {
7645            return el
7646          }
7647        ))
7648      }
7649
7650
7651      /**
7652       * @return {Bonzo}
7653       */
7654    , focus: function () {
7655        this.length && this[0].focus()
7656        return this
7657      }
7658
7659
7660      /**
7661       * @return {Bonzo}
7662       */
7663    , blur: function () {
7664        this.length && this[0].blur()
7665        return this
7666      }
7667
7668      // style getter setter & related methods
7669
7670      /**
7671       * @param {Object|string} o
7672       * @param {string=} opt_v
7673       * @return {Bonzo|string}
7674       */
7675    , css: function (o, opt_v) {
7676        var p, iter = o
7677        // is this a request for just getting a style?
7678        if (opt_v === undefined && typeof o == 'string') {
7679          // repurpose 'v'
7680          opt_v = this[0]
7681          if (!opt_v) return null
7682          if (opt_v === doc || opt_v === win) {
7683            p = (opt_v === doc) ? bonzo.doc() : bonzo.viewport()
7684            return o == 'width' ? p.width : o == 'height' ? p.height : ''
7685          }
7686          return (o = styleProperty(o)) ? getStyle(opt_v, o) : null
7687        }
7688
7689        if (typeof o == 'string') {
7690          iter = {}
7691          iter[o] = opt_v
7692        }
7693
7694        function fn(el, p, v) {
7695          for (var k in iter) {
7696            if (iter.hasOwnProperty(k)) {
7697              v = iter[k];
7698              // change "5" to "5px" - unless you're line-height, which is allowed
7699              (p = styleProperty(k)) && digit.test(v) && !(p in unitless) && (v += px)
7700              try { el.style[p] = setter(el, v) } catch(e) {}
7701            }
7702          }
7703        }
7704        return this.each(fn)
7705      }
7706
7707
7708      /**
7709       * @param {number=} opt_x
7710       * @param {number=} opt_y
7711       * @return {Bonzo|number}
7712       */
7713    , offset: function (opt_x, opt_y) {
7714        if (opt_x && typeof opt_x == 'object' && (typeof opt_x.top == 'number' || typeof opt_x.left == 'number')) {
7715          return this.each(function (el) {
7716            xy(el, opt_x.left, opt_x.top)
7717          })
7718        } else if (typeof opt_x == 'number' || typeof opt_y == 'number') {
7719          return this.each(function (el) {
7720            xy(el, opt_x, opt_y)
7721          })
7722        }
7723        if (!this[0]) return {
7724            top: 0
7725          , left: 0
7726          , height: 0
7727          , width: 0
7728        }
7729        var el = this[0]
7730          , de = el.ownerDocument.documentElement
7731          , bcr = el.getBoundingClientRect()
7732          , scroll = getWindowScroll()
7733          , width = el.offsetWidth
7734          , height = el.offsetHeight
7735          , top = bcr.top + scroll.y - Math.max(0, de && de.clientTop, doc.body.clientTop)
7736          , left = bcr.left + scroll.x - Math.max(0, de && de.clientLeft, doc.body.clientLeft)
7737
7738        return {
7739            top: top
7740          , left: left
7741          , height: height
7742          , width: width
7743        }
7744      }
7745
7746
7747      /**
7748       * @return {number}
7749       */
7750    , dim: function () {
7751        if (!this.length) return { height: 0, width: 0 }
7752        var el = this[0]
7753          , de = el.nodeType == 9 && el.documentElement // document
7754          , orig = !de && !!el.style && !el.offsetWidth && !el.offsetHeight ?
7755             // el isn't visible, can't be measured properly, so fix that
7756             function (t) {
7757               var s = {
7758                   position: el.style.position || ''
7759                 , visibility: el.style.visibility || ''
7760                 , display: el.style.display || ''
7761               }
7762               t.first().css({
7763                   position: 'absolute'
7764                 , visibility: 'hidden'
7765                 , display: 'block'
7766               })
7767               return s
7768            }(this) : null
7769          , width = de
7770              ? Math.max(el.body.scrollWidth, el.body.offsetWidth, de.scrollWidth, de.offsetWidth, de.clientWidth)
7771              : el.offsetWidth
7772          , height = de
7773              ? Math.max(el.body.scrollHeight, el.body.offsetHeight, de.scrollHeight, de.offsetHeight, de.clientHeight)
7774              : el.offsetHeight
7775
7776        orig && this.first().css(orig)
7777        return {
7778            height: height
7779          , width: width
7780        }
7781      }
7782
7783      // attributes are hard. go shopping
7784
7785      /**
7786       * @param {string} k an attribute to get or set
7787       * @param {string=} opt_v the value to set
7788       * @return {Bonzo|string}
7789       */
7790    , attr: function (k, opt_v) {
7791        var el = this[0]
7792          , n
7793
7794        if (typeof k != 'string' && !(k instanceof String)) {
7795          for (n in k) {
7796            k.hasOwnProperty(n) && this.attr(n, k[n])
7797          }
7798          return this
7799        }
7800
7801        return typeof opt_v == 'undefined' ?
7802          !el ? null : specialAttributes.test(k) ?
7803            stateAttributes.test(k) && typeof el[k] == 'string' ?
7804              true : el[k] :  el[getAttribute](k) :
7805          this.each(function (el) {
7806            specialAttributes.test(k) ? (el[k] = setter(el, opt_v)) : el[setAttribute](k, setter(el, opt_v))
7807          })
7808      }
7809
7810
7811      /**
7812       * @param {string} k
7813       * @return {Bonzo}
7814       */
7815    , removeAttr: function (k) {
7816        return this.each(function (el) {
7817          stateAttributes.test(k) ? (el[k] = false) : el.removeAttribute(k)
7818        })
7819      }
7820
7821
7822      /**
7823       * @param {string=} opt_s
7824       * @return {Bonzo|string}
7825       */
7826    , val: function (s) {
7827        return (typeof s == 'string' || typeof s == 'number') ?
7828          this.attr('value', s) :
7829          this.length ? this[0].value : null
7830      }
7831
7832      // use with care and knowledge. this data() method uses data attributes on the DOM nodes
7833      // to do this differently costs a lot more code. c'est la vie
7834      /**
7835       * @param {string|Object=} opt_k the key for which to get or set data
7836       * @param {Object=} opt_v
7837       * @return {Bonzo|Object}
7838       */
7839    , data: function (opt_k, opt_v) {
7840        var el = this[0], o, m
7841        if (typeof opt_v === 'undefined') {
7842          if (!el) return null
7843          o = data(el)
7844          if (typeof opt_k === 'undefined') {
7845            each(el.attributes, function (a) {
7846              (m = ('' + a.name).match(dattr)) && (o[camelize(m[1])] = dataValue(a.value))
7847            })
7848            return o
7849          } else {
7850            if (typeof o[opt_k] === 'undefined')
7851              o[opt_k] = dataValue(this.attr('data-' + decamelize(opt_k)))
7852            return o[opt_k]
7853          }
7854        } else {
7855          return this.each(function (el) { data(el)[opt_k] = opt_v })
7856        }
7857      }
7858
7859      // DOM detachment & related
7860
7861      /**
7862       * @return {Bonzo}
7863       */
7864    , remove: function () {
7865        this.deepEach(clearData)
7866        return this.detach()
7867      }
7868
7869
7870      /**
7871       * @return {Bonzo}
7872       */
7873    , empty: function () {
7874        return this.each(function (el) {
7875          deepEach(el.childNodes, clearData)
7876
7877          while (el.firstChild) {
7878            el.removeChild(el.firstChild)
7879          }
7880        })
7881      }
7882
7883
7884      /**
7885       * @return {Bonzo}
7886       */
7887    , detach: function () {
7888        return this.each(function (el) {
7889          el[parentNode] && el[parentNode].removeChild(el)
7890        })
7891      }
7892
7893      // who uses a mouse anyway? oh right.
7894
7895      /**
7896       * @param {number} y
7897       */
7898    , scrollTop: function (y) {
7899        return scroll.call(this, null, y, 'y')
7900      }
7901
7902
7903      /**
7904       * @param {number} x
7905       */
7906    , scrollLeft: function (x) {
7907        return scroll.call(this, x, null, 'x')
7908      }
7909
7910  }
7911
7912
7913  function cloneNode(host, el) {
7914    var c = el.cloneNode(true)
7915      , cloneElems
7916      , elElems
7917      , i
7918
7919    // check for existence of an event cloner
7920    // preferably https://github.com/fat/bean
7921    // otherwise Bonzo won't do this for you
7922    if (host.$ && typeof host.cloneEvents == 'function') {
7923      host.$(c).cloneEvents(el)
7924
7925      // clone events from every child node
7926      cloneElems = host.$(c).find('*')
7927      elElems = host.$(el).find('*')
7928
7929      for (i = 0; i < elElems.length; i++)
7930        host.$(cloneElems[i]).cloneEvents(elElems[i])
7931    }
7932    return c
7933  }
7934
7935  function isBody(element) {
7936    return element === win || (/^(?:body|html)$/i).test(element.tagName)
7937  }
7938
7939  function getWindowScroll() {
7940    return { x: win.pageXOffset || html.scrollLeft, y: win.pageYOffset || html.scrollTop }
7941  }
7942
7943  function createScriptFromHtml(html) {
7944    var scriptEl = document.createElement('script')
7945      , matches = html.match(simpleScriptTagRe)
7946    scriptEl.src = matches[1]
7947    return scriptEl
7948  }
7949
7950  /**
7951   * @param {Array.<Element>|Element|Node|string} els
7952   * @return {Bonzo}
7953   */
7954  function bonzo(els) {
7955    return new Bonzo(els)
7956  }
7957
7958  bonzo.setQueryEngine = function (q) {
7959    query = q;
7960    delete bonzo.setQueryEngine
7961  }
7962
7963  bonzo.aug = function (o, target) {
7964    // for those standalone bonzo users. this love is for you.
7965    for (var k in o) {
7966      o.hasOwnProperty(k) && ((target || Bonzo.prototype)[k] = o[k])
7967    }
7968  }
7969
7970  bonzo.create = function (node) {
7971    // hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
7972    return typeof node == 'string' && node !== '' ?
7973      function () {
7974        if (simpleScriptTagRe.test(node)) return [createScriptFromHtml(node)]
7975        var tag = node.match(/^\s*<([^\s>]+)/)
7976          , el = doc.createElement('div')
7977          , els = []
7978          , p = tag ? tagMap[tag[1].toLowerCase()] : null
7979          , dep = p ? p[2] + 1 : 1
7980          , ns = p && p[3]
7981          , pn = parentNode
7982
7983        el.innerHTML = p ? (p[0] + node + p[1]) : node
7984        while (dep--) el 
7984= el.firstChild
7985        // for IE NoScope, we may insert cruft at the begining just to get it to work
7986        if (ns && el && el.nodeType !== 1) el = el.nextSibling
7987        do {
7988          if (!tag || el.nodeType == 1) {
7989            els.push(el)
7990          }
7991        } while (el = el.nextSibling)
7992        // IE < 9 gives us a parentNode which messes up insert() check for cloning
7993        // `dep` > 1 can also cause problems with the insert() check (must do this last)
7994        each(els, function(el) { el[pn] && el[pn].removeChild(el) })
7995        return els
7996      }() : isNode(node) ? [node.cloneNode(true)] : []
7997  }
7998
7999  bonzo.doc = function () {
8000    var vp = bonzo.viewport()
8001    return {
8002        width: Math.max(doc.body.scrollWidth, html.scrollWidth, vp.width)
8003      , height: Math.max(doc.body.scrollHeight, html.scrollHeight, vp.height)
8004    }
8005  }
8006
8007  bonzo.firstChild = function (el) {
8008    for (var c = el.childNodes, i = 0, j = (c && c.length) || 0, e; i < j; i++) {
8009      if (c[i].nodeType === 1) e = c[j = i]
8010    }
8011    return e
8012  }
8013
8014  bonzo.viewport = function () {
8015    return {
8016        width: win.innerWidth
8017      , height: win.innerHeight
8018    }
8019  }
8020
8021  bonzo.isAncestor = 'compareDocumentPosition' in html ?
8022    function (container, element) {
8023      return (container.compareDocumentPosition(element) & 16) == 16
8024    } :
8025    function (container, element) {
8026      return container !== element && container.contains(element);
8027    }
8028
8029  return bonzo
8030}); // the only line we care about using a semi-colon. placed here for concatenation tools
8031
8032},{}],42:[function(require,module,exports){
8033module.exports = on;
8034module.exports.on = on;
8035module.exports.off = off;
8036
8037function on (element, event, callback, capture) {
8038  !element.addEventListener && (event = 'on' + event);
8039  (element.addEventListener || element.attachEvent).call(element, event, callback, capture);
8040  return callback;
8041}
8042
8043function off (element, event, callback, capture) {
8044  !element.removeEventListener && (event = 'on' + event);
8045  (element.removeEventListener || element.detachEvent).call(element, event, callback, capture);
8046  return callback;
8047}
8048
8049},{}],43
vendor: 13,143 bytes, lines 8049-8479
8049:[function(require,module,exports){
8050// Copyright Joyent, Inc. and other Node contributors.
8051//
8052// Permission is hereby granted, free of charge, to any person obtaining a
8053// copy of this software and associated documentation files (the
8054// "Software"), to deal in the Software without restriction, including
8055// without limitation the rights to use, copy, modify, merge, publish,
8056// distribute, sublicense, and/or sell copies of the Software, and to permit
8057// persons to whom the Software is furnished to do so, subject to the
8058// following conditions:
8059//
8060// The above copyright notice and this permission notice shall be included
8061// in all copies or substantial portions of the Software.
8062//
8063// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8064// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8065// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
8066// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
8067// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
8068// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8069// USE OR OTHER DEALINGS IN THE SOFTWARE.
8070
8071var objectCreate = Object.create || objectCreatePolyfill
8072var objectKeys = Object.keys || objectKeysPolyfill
8073var bind = Function.prototype.bind || functionBindPolyfill
8074
8075function EventEmitter() {
8076  if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) {
8077    this._events = objectCreate(null);
8078    this._eventsCount = 0;
8079  }
8080
8081  this._maxListeners = this._maxListeners || undefined;
8082}
8083module.exports = EventEmitter;
8084
8085// Backwards-compat with node 0.10.x
8086EventEmitter.EventEmitter = EventEmitter;
8087
8088EventEmitter.prototype._events = undefined;
8089EventEmitter.prototype._maxListeners = undefined;
8090
8091// By default EventEmitters will print a warning if more than 10 listeners are
8092// added to it. This is a useful default which helps finding memory leaks.
8093var defaultMaxListeners = 10;
8094
8095var hasDefineProperty;
8096try {
8097  var o = {};
8098  if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 });
8099  hasDefineProperty = o.x === 0;
8100} catch (err) { hasDefineProperty = false }
8101if (hasDefineProperty) {
8102  Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
8103    enumerable: true,
8104    get: function() {
8105      return defaultMaxListeners;
8106    },
8107    set: function(arg) {
8108      // check whether the input is a positive number (whose value is zero or
8109      // greater and not a NaN).
8110      if (typeof arg !== 'number' || arg < 0 || arg !== arg)
8111        throw new TypeError('"defaultMaxListeners" must be a positive number');
8112      defaultMaxListeners = arg;
8113    }
8114  });
8115} else {
8116  EventEmitter.defaultMaxListeners = defaultMaxListeners;
8117}
8118
8119// Obviously not all Emitters should be limited to 10. This function allows
8120// that to be increased. Set to zero for unlimited.
8121EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
8122  if (typeof n !== 'number' || n < 0 || isNaN(n))
8123    throw new TypeError('"n" argument must be a positive number');
8124  this._maxListeners = n;
8125  return this;
8126};
8127
8128function $getMaxListeners(that) {
8129  if (that._maxListeners === undefined)
8130    return EventEmitter.defaultMaxListeners;
8131  return that._maxListeners;
8132}
8133
8134EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
8135  return $getMaxListeners(this);
8136};
8137
8138// These standalone emit* functions are used to optimize calling of event
8139// handlers for fast cases because emit() itself often has a variable number of
8140// arguments and can be deoptimized because of that. These functions always have
8141// the same number of arguments and thus do not get deoptimized, so the code
8142// inside them can execute faster.
8143function emitNone(handler, isFn, self) {
8144  if (isFn)
8145    handler.call(self);
8146  else {
8147    var len = handler.length;
8148    var listeners = arrayClone(handler, len);
8149    for (var i = 0; i < len; ++i)
8150      listeners[i].call(self);
8151  }
8152}
8153function emitOne(handler, isFn, self, arg1) {
8154  if (isFn)
8155    handler.call(self, arg1);
8156  else {
8157    var len = handler.length;
8158    var listeners = arrayClone(handler, len);
8159    for (var i = 0; i < len; ++i)
8160      listeners[i].call(self, arg1);
8161  }
8162}
8163function emitTwo(handler, isFn, self, arg1, arg2) {
8164  if (isFn)
8165    handler.call(self, arg1, arg2);
8166  else {
8167    var len = handler.length;
8168    var listeners = arrayClone(handler, len);
8169    for (var i = 0; i < len; ++i)
8170      listeners[i].call(self, arg1, arg2);
8171  }
8172}
8173function emitThree(handler, isFn, self, arg1, arg2, arg3) {
8174  if (isFn)
8175    handler.call(self, arg1, arg2, arg3);
8176  else {
8177    var len = handler.length;
8178    var listeners = arrayClone(handler, len);
8179    for (var i = 0; i < len; ++i)
8180      listeners[i].call(self, arg1, arg2, arg3);
8181  }
8182}
8183
8184function emitMany(handler, isFn, self, args) {
8185  if (isFn)
8186    handler.apply(self, args);
8187  else {
8188    var len = handler.length;
8189    var listeners = arrayClone(handler, len);
8190    for (var i = 0; i < len; ++i)
8191      listeners[i].apply(self, args);
8192  }
8193}
8194
8195EventEmitter.prototype.emit = function emit(type) {
8196  var er, handler, len, args, i, events;
8197  var doError = (type === 'error');
8198
8199  events = this._events;
8200  if (events)
8201    doError = (doError && events.error == null);
8202  else if (!doError)
8203    return false;
8204
8205  // If there is no 'error' event listener then throw.
8206  if (doError) {
8207    if (arguments.length > 1)
8208      er = arguments[1];
8209    if (er instanceof Error) {
8210      throw er; // Unhandled 'error' event
8211    } else {
8212      // At least give some kind of context to the user
8213      var err = new Error('Unhandled "error" event. (' + er + ')');
8214      err.context = er;
8215      throw err;
8216    }
8217    return false;
8218  }
8219
8220  handler = events[type];
8221
8222  if (!handler)
8223    return false;
8224
8225  var isFn = typeof handler === 'function';
8226  len = arguments.length;
8227  switch (len) {
8228      // fast cases
8229    case 1:
8230      emitNone(handler, isFn, this);
8231      break;
8232    case 2:
8233      emitOne(handler, isFn, this, arguments[1]);
8234      break;
8235    case 3:
8236      emitTwo(handler, isFn, this, arguments[1], arguments[2]);
8237      break;
8238    case 4:
8239      emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
8240      break;
8241      // slower
8242    default:
8243      args = new Array(len - 1);
8244      for (i = 1; i < len; i++)
8245        args[i - 1] = arguments[i];
8246      emitMany(handler, isFn, this, args);
8247  }
8248
8249  return true;
8250};
8251
8252function _addListener(target, type, listener, prepend) {
8253  var m;
8254  var events;
8255  var existing;
8256
8257  if (typeof listener !== 'function')
8258    throw new TypeError('"listener" argument must be a function');
8259
8260  events = target._events;
8261  if (!events) {
8262    events = target._events = objectCreate(null);
8263    target._eventsCount = 0;
8264  } else {
8265    // To avoid recursion in the case that type === "newListener"! Before
8266    // adding it to the listeners, first emit "newListener".
8267    if (events.newListener) {
8268      target.emit('newListener', type,
8269          listener.listener ? listener.listener : listener);
8270
8271      // Re-assign `events` because a newListener handler could have caused the
8272      // this._events to be assigned to a new object
8273      events = target._events;
8274    }
8275    existing = events[type];
8276  }
8277
8278  if (!existing) {
8279    // Optimize the case of one listener. Don't need the extra array object.
8280    existing = events[type] = listener;
8281    ++target._eventsCount;
8282  } else {
8283    if (typeof existing === 'function') {
8284      // Adding the second element, need to change to array.
8285      existing = events[type] =
8286          prepend ? [listener, existing] : [existing, listener];
8287    } else {
8288      // If we've already got an array, just append.
8289      if (prepend) {
8290        existing.unshift(listener);
8291      } else {
8292        existing.push(listener);
8293      }
8294    }
8295
8296    // Check for listener leak
8297    if (!existing.warned) {
8298      m = $getMaxListeners(target);
8299      if (m && m > 0 && existing.length > m) {
8300        existing.warned = true;
8301        var w = new Error('Possible EventEmitter memory leak detected. ' +
8302            existing.length + ' "' + String(type) + '" listeners ' +
8303            'added. Use emitter.setMaxListeners() to ' +
8304            'increase limit.');
8305        w.name = 'MaxListenersExceededWarning';
8306        w.emitter = target;
8307        w.type = type;
8308        w.count = existing.length;
8309        if (typeof console === 'object' && console.warn) {
8310          console.warn('%s: %s', w.name, w.message);
8311        }
8312      }
8313    }
8314  }
8315
8316  return target;
8317}
8318
8319EventEmitter.prototype.addListener = function addListener(type, listener) {
8320  return _addListener(this, type, listener, false);
8321};
8322
8323EventEmitter.prototype.on = EventEmitter.prototype.addListener;
8324
8325EventEmitter.prototype.prependListener =
8326    function prependListener(type, listener) {
8327      return _addListener(this, type, listener, true);
8328    };
8329
8330function onceWrapper() {
8331  if (!this.fired) {
8332    this.target.removeListener(this.type, this.wrapFn);
8333    this.fired = true;
8334    switch (arguments.length) {
8335      case 0:
8336        return this.listener.call(this.target);
8337      case 1:
8338        return this.listener.call(this.target, arguments[0]);
8339      case 2:
8340        return this.listener.call(this.target, arguments[0], arguments[1]);
8341      case 3:
8342        return this.listener.call(this.target, arguments[0], arguments[1],
8343            arguments[2]);
8344      default:
8345        var args = new Array(arguments.length);
8346        for (var i = 0; i < args.length; ++i)
8347          args[i] = arguments[i];
8348        this.listener.apply(this.target, args);
8349    }
8350  }
8351}
8352
8353function _onceWrap(target, type, listener) {
8354  var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
8355  var wrapped = bind.call(onceWrapper, state);
8356  wrapped.listener = listener;
8357  state.wrapFn = wrapped;
8358  return wrapped;
8359}
8360
8361EventEmitter.prototype.once = function once(type, listener) {
8362  if (typeof listener !== 'function')
8363    throw new TypeError('"listener" argument must be a function');
8364  this.on(type, _onceWrap(this, type, listener));
8365  return this;
8366};
8367
8368EventEmitter.prototype.prependOnceListener =
8369    function prependOnceListener(type, listener) {
8370      if (typeof listener !== 'function')
8371        throw new TypeError('"listener" argument must be a function');
8372      this.prependListener(type, _onceWrap(this, type, listener));
8373      return this;
8374    };
8375
8376// Emits a 'removeListener' event if and only if the listener was removed.
8377EventEmitter.prototype.removeListener =
8378    function removeListener(type, listener) {
8379      var list, events, position, i, originalListener;
8380
8381      if (typeof listener !== 'function')
8382        throw new TypeError('"listener" argument must be a function');
8383
8384      events = this._events;
8385      if (!events)
8386        return this;
8387
8388      list = events[type];
8389      if (!list)
8390        return this;
8391
8392      if (list === listener || list.listener === listener) {
8393        if (--this._eventsCount === 0)
8394          this._events = objectCreate(null);
8395        else {
8396          delete events[type];
8397          if (events.removeListener)
8398            this.emit('removeListener', type, list.listener || listener);
8399        }
8400      } else if (typeof list !== 'function') {
8401        position = -1;
8402
8403        for (i = list.length - 1; i >= 0; i--) {
8404          if (list[i] === listener || list[i].listener === listener) {
8405            originalListener = list[i].listener;
8406            position = i;
8407            break;
8408          }
8409        }
8410
8411        if (position < 0)
8412          return this;
8413
8414        if (position === 0)
8415          list.shift();
8416        else
8417          spliceOne(list, position);
8418
8419        if (list.length === 1)
8420          events[type] = list[0];
8421
8422        if (events.removeListener)
8423          this.emit('removeListener', type, originalListener || listener);
8424      }
8425
8426      return this;
8427    };
8428
8429EventEmitter.prototype.removeAllListeners =
8430    function removeAllListeners(type) {
8431      var listeners, events, i;
8432
8433      events = this._events;
8434      if (!events)
8435        return this;
8436
8437      // not listening for removeListener, no need to emit
8438      if (!events.removeListener) {
8439        if (arguments.length === 0) {
8440          this._events = objectCreate(null);
8441          this._eventsCount = 0;
8442        } else if (events[type]) {
8443          if (--this._eventsCount === 0)
8444            this._events = objectCreate(null);
8445          else
8446            delete events[type];
8447        }
8448        return this;
8449      }
8450
8451      // emit removeListener for all listeners on all events
8452      if (arguments.length === 0) {
8453        var keys = objectKeys(events);
8454        var key;
8455        for (i = 0; i < keys.length; ++i) {
8456          key = keys[i];
8457          if (key === 'removeListener') continue;
8458          this.removeAllListeners(key);
8459        }
8460        this.removeAllListeners('removeListener');
8461        this._events = objectCreate(null);
8462        this._eventsCount = 0;
8463        return this;
8464      }
8465
8466      listeners = events[type];
8467
8468      if (typeof listeners === 'function') {
8469        this.removeListener(type, listeners);
8470      } else if (listeners) {
8471        // LIFO order
8472        for (i = listeners.length - 1; i >= 0; i--) {
8473          this.removeListener(type, listeners[i]);
8474        }
8475      }
8476
8477      return this;
8478    };
8479
8480EventEmitter.prototype.listeners = function listeners(type) {
8481  var evlistener;
8482  var ret;
8483  var events = this._events;
8484
8485  if (!events)
8486    ret = [];
8487  else {
8488    evlistener = events[type];
8489    if (!evlistener)
8490      ret = [];
8491    else if (typeof evlistener === 'function')
8492      ret = [evlistener.listener || evlistener];
8493    else
8494      ret = unwrapListeners(evlistener);
8495  }
8496
8497  return ret;
8498};
8499
8500EventEmitter.listenerCount = function(emitter, type) {
8501  if (typeof emitter.listenerCount === 'function') {
8502    return emitter.listenerCount(type);
8503  } else {
8504    return listenerCount.call(emitter, type);
8505  }
8506};
8507
8508EventEmitter.prototype.listenerCount = listenerCount;
8509function listenerCount(type) {
8510  var events = this._events;
8511
8512  if (events) {
8513    var evlistener = events[type];
8514
8515    if (typeof evlistener === 'function') {
8516      return 1;
8517    } else if (evlistener) {
8518      return evlistener.length;
8519    }
8520  }
8521
8522  return 0;
8523}
8524
8525EventEmitter.prototype.eventNames = function eventNames() {
8526  return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
8527};
8528
8529// About 1.5x faster than the two-arg version of Array#splice().
8530function spliceOne(list, index) {
8531  for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
8532    list[i] = list[k];
8533  list.pop();
8534}
8535
8536function arrayClone(arr, n) {
8537  var copy = new Array(n);
8538  for (var i = 0; i < n; ++i)
8539    copy[i] = arr[i];
8540  return copy;
8541}
8542
8543function unwrapListeners(arr) {
8544  var ret = new Array(arr.length);
8545  for (var i = 0; i < ret.length; ++i) {
8546    ret[i] = arr[i].listener || arr[i];
8547  }
8548  return ret;
8549}
8550
8551function objectCreatePolyfill(proto) {
8552  var F = function() {};
8553  F.prototype = proto;
8554  return new F;
8555}
8556function objectKeysPolyfill(obj) {
8557  var keys = [];
8558  for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
8559    keys.push(k);
8560  }
8561  return k;
8562}
8563function functionBindPolyfill(context) {
8564  var fn = this;
8565  return function () {
8566    return fn.apply(context, arguments);
8567  };
8568}
8569
8570},{}],44:[function(require,module,exports){
8571if (typeof Object.create === 'function') {
8572  // implementation from standard node.js 'util' module
8573  module.exports = function inherits(ctor, superCtor) {
8574    ctor.super_ = superCtor
8575    ctor.prototype = Object.create(superCtor.prototype, {
8576      constructor: {
8577        value: ctor,
8578        enumerable: false,
8579        writable: true,
8580        configurable: true
8581      }
8582    });
8583  };
8584} else {
8585  // old school shim for old browsers
8586  module.exports = function inherits(ctor, superCtor) {
8587    ctor.super_ = superCtor
8588    var TempCtor = function () {}
8589    TempCtor.prototype = superCtor.prototype
8590    ctor.prototype = new TempCtor()
8591    ctor.prototype.constructor = ctor
8592  }
8593}
8594
8595},{}],45:[function(require,module,exports){
8596/*!
8597 * mustache.js - Logic-less {{mustache}} templates with JavaScript
8598 * http://github.com/janl/mustache.js
8599 */
8600
8601/*global define: false Mustache: true*/
8602
8603(function defineMustache (global, factory) {
8604  if (typeof exports === 'object' && exports && typeof exports.nodeName !== 'string') {
8605    factory(exports); // CommonJS
8606  } else if (typeof define === 'function' && define.amd) {
8607    define(['exports'], factory); // AMD
8608  } else {
8609    global.Mustache = {};
8610    factory(global.Mustache); // script, wsh, asp
8611  }
8612}(this, function mustacheFactory (mustache) {
8613
8614  var objectToString = Object.prototype.toString;
8615  var isArray = Array.isArray || function isArrayPolyfill (object) {
8616    return objectToString.call(object) === '[object Array]';
8617  };
8618
8619  function isFunction (object) {
8620    return typeof object === 'function';
8621  }
8622
8623  /**
8624   * More correct typeof string handling array
8625   * which normally returns typeof 'object'
8626   */
8627  function typeStr (obj) {
8628    return isArray(obj) ? 'array' : typeof obj;
8629  }
8630
8631  function escapeRegExp (string) {
8632    return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
8633  }
8634
8635  /**
8636   * Null safe way of checking whether or not an object,
8637   * including its prototype, has a given property
8638   */
8639  function hasProperty (obj, propName) {
8640    return obj != null && typeof obj === 'object' && (propName in obj);
8641  }
8642
8643  // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
8644  // See https://github.com/janl/mustache.js/issues/189
8645  var regExpTest = RegExp.prototype.test;
8646  function testRegExp (re, string) {
8647    return regExpTest.call(re, string);
8648  }
8649
8650  var nonSpaceRe = /\S/;
8651  function isWhitespace (string) {
8652    return !testRegExp(nonSpaceRe, string);
8653  }
8654
8655  var entityMap = {
8656    '&': '&amp;',
8657    '<': '&lt;',
8658    '>': '&gt;',
8659    '"': '&quot;',
8660    "'": '&#39;',
8661    '/': '&#x2F;',
8662    '`': '&#x60;',
8663    '=': '&#x3D;'
8664  };
8665
8666  function escapeHtml (string) {
8667    return String(string).replace(/[&<>
vendor: 17,446 bytes, lines 8667-9227
8667"'`=\/]/g, function fromEntityMap (s) {
8668      return entityMap[s];
8669    });
8670  }
8671
8672  var whiteRe = /\s*/;
8673  var spaceRe = /\s+/;
8674  var equalsRe = /\s*=/;
8675  var curlyRe = /\s*\}/;
8676  var tagRe = /#|\^|\/|>|\{|&|=|!/;
8677
8678  /**
8679   * Breaks up the given `template` string into a tree of tokens. If the `tags`
8680   * argument is given here it must be an array with two string values: the
8681   * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
8682   * course, the default is to use mustaches (i.e. mustache.tags).
8683   *
8684   * A token is an array with at least 4 elements. The first element is the
8685   * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
8686   * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
8687   * all text that appears outside a symbol this element is "text".
8688   *
8689   * The second element of a token is its "value". For mustache tags this is
8690   * whatever else was inside the tag besides the opening symbol. For text tokens
8691   * this is the text itself.
8692   *
8693   * The third and fourth elements of the token are the start and end indices,
8694   * respectively, of the token in the original template.
8695   *
8696   * Tokens that are the root node of a subtree contain two more elements: 1) an
8697   * array of tokens in the subtree and 2) the index in the original template at
8698   * which the closing tag for that section begins.
8699   */
8700  function parseTemplate (template, tags) {
8701    if (!template)
8702      return [];
8703
8704    var sections = [];     // Stack to hold section tokens
8705    var tokens = [];       // Buffer to hold the tokens
8706    var spaces = [];       // Indices of whitespace tokens on the current line
8707    var hasTag = false;    // Is there a {{tag}} on the current line?
8708    var nonSpace = false;  // Is there a non-space char on the current line?
8709
8710    // Strips all whitespace tokens array for the current line
8711    // if there was a {{#tag}} on it and otherwise only space.
8712    function stripSpace () {
8713      if (hasTag && !nonSpace) {
8714        while (spaces.length)
8715          delete tokens[spaces.pop()];
8716      } else {
8717        spaces = [];
8718      }
8719
8720      hasTag = false;
8721      nonSpace = false;
8722    }
8723
8724    var openingTagRe, closingTagRe, closingCurlyRe;
8725    function compileTags (tagsToCompile) {
8726      if (typeof tagsToCompile === 'string')
8727        tagsToCompile = tagsToCompile.split(spaceRe, 2);
8728
8729      if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)
8730        throw new Error('Invalid tags: ' + tagsToCompile);
8731
8732      openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*');
8733      closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1]));
8734      closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1]));
8735    }
8736
8737    compileTags(tags || mustache.tags);
8738
8739    var scanner = new Scanner(template);
8740
8741    var start, type, value, chr, token, openSection;
8742    while (!scanner.eos()) {
8743      start = scanner.pos;
8744
8745      // Match any text between tags.
8746      value = scanner.scanUntil(openingTagRe);
8747
8748      if (value) {
8749        for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
8750          chr = value.charAt(i);
8751
8752          if (isWhitespace(chr)) {
8753            spaces.push(tokens.length);
8754          } else {
8755            nonSpace = true;
8756          }
8757
8758          tokens.push([ 'text', chr, start, start + 1 ]);
8759          start += 1;
8760
8761          // Check for whitespace on the current line.
8762          if (chr === '\n')
8763            stripSpace();
8764        }
8765      }
8766
8767      // Match the opening tag.
8768      if (!scanner.scan(openingTagRe))
8769        break;
8770
8771      hasTag = true;
8772
8773      // Get the tag type.
8774      type = scanner.scan(tagRe) || 'name';
8775      scanner.scan(whiteRe);
8776
8777      // Get the tag value.
8778      if (type === '=') {
8779        value = scanner.scanUntil(equalsRe);
8780        scanner.scan(equalsRe);
8781        scanner.scanUntil(closingTagRe);
8782      } else if (type === '{') {
8783        value = scanner.scanUntil(closingCurlyRe);
8784        scanner.scan(curlyRe);
8785        scanner.scanUntil(closingTagRe);
8786        type = '&';
8787      } else {
8788        value = scanner.scanUntil(closingTagRe);
8789      }
8790
8791      // Match the closing tag.
8792      if (!scanner.scan(closingTagRe))
8793        throw new Error('Unclosed tag at ' + scanner.pos);
8794
8795      token = [ type, value, start, scanner.pos ];
8796      tokens.push(token);
8797
8798      if (type === '#' || type === '^') {
8799        sections.push(token);
8800      } else if (type === '/') {
8801        // Check section nesting.
8802        openSection = sections.pop();
8803
8804        if (!openSection)
8805          throw new Error('Unopened section "' + value + '" at ' + start);
8806
8807        if (openSection[1] !== value)
8808          throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
8809      } else if (type === 'name' || type === '{' || type === '&') {
8810        nonSpace = true;
8811      } else if (type === '=') {
8812        // Set the tags for the next time around.
8813        compileTags(value);
8814      }
8815    }
8816
8817    // Make sure there are no open sections when we're done.
8818    openSection = sections.pop();
8819
8820    if (openSection)
8821      throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
8822
8823    return nestTokens(squashTokens(tokens));
8824  }
8825
8826  /**
8827   * Combines the values of consecutive text tokens in the given `tokens` array
8828   * to a single token.
8829   */
8830  function squashTokens (tokens) {
8831    var squashedTokens = [];
8832
8833    var token, lastToken;
8834    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
8835      token = tokens[i];
8836
8837      if (token) {
8838        if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
8839          lastToken[1] += token[1];
8840          lastToken[3] = token[3];
8841        } else {
8842          squashedTokens.push(token);
8843          lastToken = token;
8844        }
8845      }
8846    }
8847
8848    return squashedTokens;
8849  }
8850
8851  /**
8852   * Forms the given array of `tokens` into a nested tree structure where
8853   * tokens that represent a section have two additional items: 1) an array of
8854   * all tokens that appear in that section and 2) the index in the original
8855   * template that represents the end of that section.
8856   */
8857  function nestTokens (tokens) {
8858    var nestedTokens = [];
8859    var collector = nestedTokens;
8860    var sections = [];
8861
8862    var token, section;
8863    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
8864      token = tokens[i];
8865
8866      switch (token[0]) {
8867        case '#':
8868        case '^':
8869          collector.push(token);
8870          sections.push(token);
8871          collector = token[4] = [];
8872          break;
8873        case '/':
8874          section = sections.pop();
8875          section[5] = token[2];
8876          collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
8877          break;
8878        default:
8879          collector.push(token);
8880      }
8881    }
8882
8883    return nestedTokens;
8884  }
8885
8886  /**
8887   * A simple string scanner that is used by the template parser to find
8888   * tokens in template strings.
8889   */
8890  function Scanner (string) {
8891    this.string = string;
8892    this.tail = string;
8893    this.pos = 0;
8894  }
8895
8896  /**
8897   * Returns `true` if the tail is empty (end of string).
8898   */
8899  Scanner.prototype.eos = function eos () {
8900    return this.tail === '';
8901  };
8902
8903  /**
8904   * Tries to match the given regular expression at the current position.
8905   * Returns the matched text if it can match, the empty string otherwise.
8906   */
8907  Scanner.prototype.scan = function scan (re) {
8908    var match = this.tail.match(re);
8909
8910    if (!match || match.index !== 0)
8911      return '';
8912
8913    var string = match[0];
8914
8915    this.tail = this.tail.substring(string.length);
8916    this.pos += string.length;
8917
8918    return string;
8919  };
8920
8921  /**
8922   * Skips all text until the given regular expression can be matched. Returns
8923   * the skipped string, which is the entire tail if no match can be made.
8924   */
8925  Scanner.prototype.scanUntil = function scanUntil (re) {
8926    var index = this.tail.search(re), match;
8927
8928    switch (index) {
8929      case -1:
8930        match = this.tail;
8931        this.tail = '';
8932        break;
8933      case 0:
8934        match = '';
8935        break;
8936      default:
8937        match = this.tail.substring(0, index);
8938        this.tail = this.tail.substring(index);
8939    }
8940
8941    this.pos += match.length;
8942
8943    return match;
8944  };
8945
8946  /**
8947   * Represents a rendering context by wrapping a view object and
8948   * maintaining a reference to the parent context.
8949   */
8950  function Context (view, parentContext) {
8951    this.view = view;
8952    this.cache = { '.': this.view };
8953    this.parent = parentContext;
8954  }
8955
8956  /**
8957   * Creates a new context using the given view with this context
8958   * as the parent.
8959   */
8960  Context.prototype.push = function push (view) {
8961    return new Context(view, this);
8962  };
8963
8964  /**
8965   * Returns the value of the given name in this context, traversing
8966   * up the context hierarchy if the value is absent in this context's view.
8967   */
8968  Context.prototype.lookup = function lookup (name) {
8969    var cache = this.cache;
8970
8971    var value;
8972    if (cache.hasOwnProperty(name)) {
8973      value = cache[name];
8974    } else {
8975      var context = this, names, index, lookupHit = false;
8976
8977      while (context) {
8978        if (name.indexOf('.') > 0) {
8979          value = context.view;
8980          names = name.split('.');
8981          index = 0;
8982
8983          /**
8984           * Using the dot notion path in `name`, we descend through the
8985           * nested objects.
8986           *
8987           * To be certain that the lookup has been successful, we have to
8988           * check if the last object in the path actually has the property
8989           * we are looking for. We store the result in `lookupHit`.
8990           *
8991           * This is specially necessary for when the value has been set to
8992           * `undefined` and we want to avoid looking up parent contexts.
8993           **/
8994          while (value != null && index < names.length) {
8995            if (index === names.length - 1)
8996              lookupHit = hasProperty(value, names[index]);
8997
8998            value = value[names[index++]];
8999          }
9000        } else {
9001          value = context.view[name];
9002          lookupHit = hasProperty(context.view, name);
9003        }
9004
9005        if (lookupHit)
9006          break;
9007
9008        context = context.parent;
9009      }
9010
9011      cache[name] = value;
9012    }
9013
9014    if (isFunction(value))
9015      value = value.call(this.view);
9016
9017    return value;
9018  };
9019
9020  /**
9021   * A Writer knows how to take a stream of tokens and render them to a
9022   * string, given a context. It also maintains a cache of templates to
9023   * avoid the need to parse the same template twice.
9024   */
9025  function Writer () {
9026    this.cache = {};
9027  }
9028
9029  /**
9030   * Clears all cached templates in this writer.
9031   */
9032  Writer.prototype.clearCache = function clearCache () {
9033    this.cache = {};
9034  };
9035
9036  /**
9037   * Parses and caches the given `template` and returns the array of tokens
9038   * that is generated from the parse.
9039   */
9040  Writer.prototype.parse = function parse (template, tags) {
9041    var cache = this.cache;
9042    var tokens = cache[template];
9043
9044    if (tokens == null)
9045      tokens = cache[template] = parseTemplate(template, tags);
9046
9047    return tokens;
9048  };
9049
9050  /**
9051   * High-level method that is used to render the given `template` with
9052   * the given `view`.
9053   *
9054   * The optional `partials` argument may be an object that contains the
9055   * names and templates of partials that are used in the template. It may
9056   * also be a function that is used to load partial templates on the fly
9057   * that takes a single argument: the name of the partial.
9058   */
9059  Writer.prototype.render = function render (template, view, partials) {
9060    var tokens = this.parse(template);
9061    var context = (view instanceof Context) ? view : new Context(view);
9062    return this.renderTokens(tokens, context, partials, template);
9063  };
9064
9065  /**
9066   * Low-level method that renders the given array of `tokens` using
9067   * the given `context` and `partials`.
9068   *
9069   * Note: The `originalTemplate` is only ever used to extract the portion
9070   * of the original template that was contained in a higher-order section.
9071   * If the template doesn't use higher-order sections, this argument may
9072   * be omitted.
9073   */
9074  Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate) {
9075    var buffer = '';
9076
9077    var token, symbol, value;
9078    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
9079      value = undefined;
9080      token = tokens[i];
9081      symbol = token[0];
9082
9083      if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);
9084      else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);
9085      else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);
9086      else if (symbol === '&') value = this.unescapedValue(token, context);
9087      else if (symbol === 'name') value = this.escapedValue(token, context);
9088      else if (symbol === 'text') value = this.rawValue(token);
9089
9090      if (value !== undefined)
9091        buffer += value;
9092    }
9093
9094    return buffer;
9095  };
9096
9097  Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate) {
9098    var self = this;
9099    var buffer = '';
9100    var value = context.lookup(token[1]);
9101
9102    // This function is used to render an arbitrary template
9103    // in the current context by higher-order sections.
9104    function subRender (template) {
9105      return self.render(template, context, partials);
9106    }
9107
9108    if (!value) return;
9109
9110    if (isArray(value)) {
9111      for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
9112        buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
9113      }
9114    } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {
9115      buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
9116    } else if (isFunction(value)) {
9117      if (typeof originalTemplate !== 'string')
9118        throw new Error('Cannot use higher-order sections without the original template');
9119
9120      // Extract the portion of the original template that the section contains.
9121      value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
9122
9123      if (value != null)
9124        buffer += value;
9125    } else {
9126      buffer += this.renderTokens(token[4], context, partials, originalTemplate);
9127    }
9128    return buffer;
9129  };
9130
9131  Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate) {
9132    var value = context.lookup(token[1]);
9133
9134    // Use JavaScript's definition of falsy. Include empty arrays.
9135    // See https://github.com/janl/mustache.js/issues/186
9136    if (!value || (isArray(value) && value.length === 0))
9137      return this.renderTokens(token[4], context, partials, originalTemplate);
9138  };
9139
9140  Writer.prototype.renderPartial = function renderPartial (token, context, partials) {
9141    if (!partials) return;
9142
9143    var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
9144    if (value != null)
9145      return this.renderTokens(this.parse(value), context, partials, value);
9146  };
9147
9148  Writer.prototype.unescapedValue = function unescapedValue (token, context) {
9149    var value = context.lookup(token[1]);
9150    if (value != null)
9151      return value;
9152  };
9153
9154  Writer.prototype.escapedValue = function escapedValue (token, context) {
9155    var value = context.lookup(token[1]);
9156    if (value != null)
9157      return mustache.escape(value);
9158  };
9159
9160  Writer.prototype.rawValue = function rawValue (token) {
9161    return token[1];
9162  };
9163
9164  mustache.name = 'mustache.js';
9165  mustache.version = '2.3.0';
9166  mustache.tags = [ '{{', '}}' ];
9167
9168  // All high-level mustache.* functions use this writer.
9169  var defaultWriter = new Writer();
9170
9171  /**
9172   * Clears all cached templates in the default writer.
9173   */
9174  mustache.clearCache = function clearCache () {
9175    return defaultWriter.clearCache();
9176  };
9177
9178  /**
9179   * Parses and caches the given template in the default writer and returns the
9180   * array of tokens it contains. Doing this ahead of time avoids the need to
9181   * parse templates on the fly as they are rendered.
9182   */
9183  mustache.parse = function parse (template, tags) {
9184    return defaultWriter.parse(template, tags);
9185  };
9186
9187  /**
9188   * Renders the `template` with the given `view` and `partials` using the
9189   * default writer.
9190   */
9191  mustache.render = function render (template, view, partials) {
9192    if (typeof template !== 'string') {
9193      throw new TypeError('Invalid template! Template should be a "string" ' +
9194                          'but "' + typeStr(template) + '" was given as the first ' +
9195                          'argument for mustache#render(template, view, partials)');
9196    }
9197
9198    return defaultWriter.render(template, view, partials);
9199  };
9200
9201  // This is here for backwards compatibility with 0.4.x.,
9202  /*eslint-disable */ // eslint wants camel cased function name
9203  mustache.to_html = function to_html (template, view, partials, send) {
9204    /*eslint-enable*/
9205
9206    var result = mustache.render(template, view, partials);
9207
9208    if (isFunction(send)) {
9209      send(result);
9210    } else {
9211      return result;
9212    }
9213  };
9214
9215  // Export the escaping function so that the user may override it.
9216  // See https://github.com/janl/mustache.js/issues/244
9217  mustache.escape = escapeHtml;
9218
9219  // Export these mainly for testing, but also for advanced usage.
9220  mustache.Scanner = Scanner;
9221  mustache.Context = Context;
9222  mustache.Writer = Writer;
9223
9224  return mustache;
9225}));
9226
9227},{}],46
vendor: 5,461 bytes, lines 9227-9413
9227:[function(require,module,exports){
9228// shim for using process in browser
9229var process = module.exports = {};
9230
9231// cached from whatever global is present so that test runners that stub it
9232// don't break things.  But we need to wrap it in a try catch in case it is
9233// wrapped in strict mode code which doesn't define any globals.  It's inside a
9234// function because try/catches deoptimize in certain engines.
9235
9236var cachedSetTimeout;
9237var cachedClearTimeout;
9238
9239function defaultSetTimout() {
9240    throw new Error('setTimeout has not been defined');
9241}
9242function defaultClearTimeout () {
9243    throw new Error('clearTimeout has not been defined');
9244}
9245(function () {
9246    try {
9247        if (typeof setTimeout === 'function') {
9248            cachedSetTimeout = setTimeout;
9249        } else {
9250            cachedSetTimeout = defaultSetTimout;
9251        }
9252    } catch (e) {
9253        cachedSetTimeout = defaultSetTimout;
9254    }
9255    try {
9256        if (typeof clearTimeout === 'function') {
9257            cachedClearTimeout = clearTimeout;
9258        } else {
9259            cachedClearTimeout = defaultClearTimeout;
9260        }
9261    } catch (e) {
9262        cachedClearTimeout = defaultClearTimeout;
9263    }
9264} ())
9265function runTimeout(fun) {
9266    if (cachedSetTimeout === setTimeout) {
9267        //normal enviroments in sane situations
9268        return setTimeout(fun, 0);
9269    }
9270    // if setTimeout wasn't available but was latter defined
9271    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
9272        cachedSetTimeout = setTimeout;
9273        return setTimeout(fun, 0);
9274    }
9275    try {
9276        // when when somebody has screwed with setTimeout but no I.E. maddness
9277        return cachedSetTimeout(fun, 0);
9278    } catch(e){
9279        try {
9280            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
9281            return cachedSetTimeout.call(null, fun, 0);
9282        } catch(e){
9283            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
9284            return cachedSetTimeout.call(this, fun, 0);
9285        }
9286    }
9287
9288
9289}
9290function runClearTimeout(marker) {
9291    if (cachedClearTimeout === clearTimeout) {
9292        //normal enviroments in sane situations
9293        return clearTimeout(marker);
9294    }
9295    // if clearTimeout wasn't available but was latter defined
9296    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
9297        cachedClearTimeout = clearTimeout;
9298        return clearTimeout(marker);
9299    }
9300    try {
9301        // when when somebody has screwed with setTimeout but no I.E. maddness
9302        return cachedClearTimeout(marker);
9303    } catch (e){
9304        try {
9305            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
9306            return cachedClearTimeout.call(null, marker);
9307        } catch (e){
9308            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
9309            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
9310            return cachedClearTimeout.call(this, marker);
9311        }
9312    }
9313
9314
9315
9316}
9317var queue = [];
9318var draining = false;
9319var currentQueue;
9320var queueIndex = -1;
9321
9322function cleanUpNextTick() {
9323    if (!draining || !currentQueue) {
9324        return;
9325    }
9326    draining = false;
9327    if (currentQueue.length) {
9328        queue = currentQueue.concat(queue);
9329    } else {
9330        queueIndex = -1;
9331    }
9332    if (queue.length) {
9333        drainQueue();
9334    }
9335}
9336
9337function drainQueue() {
9338    if (draining) {
9339        return;
9340    }
9341    var timeout = runTimeout(cleanUpNextTick);
9342    draining = true;
9343
9344    var len = queue.length;
9345    while(len) {
9346        currentQueue = queue;
9347        queue = [];
9348        while (++queueIndex < len) {
9349            if (currentQueue) {
9350                currentQueue[queueIndex].run();
9351            }
9352        }
9353        queueIndex = -1;
9354        len = queue.length;
9355    }
9356    currentQueue = null;
9357    draining = false;
9358    runClearTimeout(timeout);
9359}
9360
9361process.nextTick = function (fun) {
9362    var args = new Array(arguments.length - 1);
9363    if (arguments.length > 1) {
9364        for (var i = 1; i < arguments.length; i++) {
9365            args[i - 1] = arguments[i];
9366        }
9367    }
9368    queue.push(new Item(fun, args));
9369    if (queue.length === 1 && !draining) {
9370        runTimeout(drainQueue);
9371    }
9372};
9373
9374// v8 likes predictible objects
9375function Item(fun, array) {
9376    this.fun = fun;
9377    this.array = array;
9378}
9379Item.prototype.run = function () {
9380    this.fun.apply(null, this.array);
9381};
9382process.title = 'browser';
9383process.browser = true;
9384process.env = {};
9385process.argv = [];
9386process.version = ''; // empty string to avoid regexp issues
9387process.versions = {};
9388
9389function noop() {}
9390
9391process.on = noop;
9392process.addListener = noop;
9393process.once = noop;
9394process.off = noop;
9395process.removeListener = noop;
9396process.removeAllListeners = noop;
9397process.emit = noop;
9398process.prependListener = noop;
9399process.prependOnceListener = noop;
9400
9401process.listeners = function (name) { return [] }
9402
9403process.binding = function (name) {
9404    throw new Error('process.binding is not supported');
9405};
9406
9407process.cwd = function () { return '/' };
9408process.chdir = function (dir) {
9409    throw new Error('process.chdir is not supported');
9410};
9411process.umask = function() { return 0; };
9412
9413},{}],
941347:[function(require,module,exports){
9414/*!
9415  * @preserve Qwery - A selector engine
9416  * https://github.com/ded/qwery
9417  * (c) Dustin Diaz 2014 | License MIT
9418  */
9419
9420(function (name, context, definition) {
9421  if (typeof module != 'undefined' && module.exports) module.exports = definition()
9422  else if (typeof define == 'function' && define.amd) define(definition)
9423  else context[name] = definition()
9424})('qwery', this, function () {
9425
9426  var classOnly = /^\.([\w\-]+)$/
9427    , doc = document
9428    , win = window
9429    , html = doc.documentElement
9430    , nodeType = 'nodeType'
9431  var isAncestor = 'compareDocumentPosition' in html ?
9432    function (element, container) {
9433      return (container.compareDocumentPosition(element) & 16) == 16
9434    } :
9435    function (element, container) {
9436      container = container == doc || container == window ? html : container
9437      return container !== element && container.contains(element)
9438    }
9439
9440  function toArray(ar) {
9441    return [].slice.call(ar, 0)
9442  }
9443
9444  function isNode(el) {
9445    var t
9446    return el && typeof el === 'object' && (t = el.nodeType) && (t == 1 || t == 9)
9447  }
9448
9449  function arrayLike(o) {
9450    return (typeof o === 'object' && isFinite(o.length))
9451  }
9452
9453  function flatten(ar) {
9454    for (var r = [], i = 0, l = ar.length; i < l; ++i) arrayLike(ar[i]) ? (r = r.concat(ar[i])) : (r[r.length] = ar[i])
9455    return r
9456  }
9457
9458  function uniq(ar) {
9459    var a = [], i, j
9460    label:
9461    for (i = 0; i < ar.length; i++) {
9462      for (j = 0; j < a.length; j++) {
9463        if (a[j] == ar[i]) {
9464          continue label
9465        }
9466      }
9467      a[a.length] = ar[i]
9468    }
9469    return a
9470  }
9471
9472
9473  function normalizeRoot(root) {
9474    if (!root) return doc
9475    if (typeof root == 'string') return qwery(root)[0]
9476    if (!root[nodeType] && arrayLike(root)) return root[0]
9477    return root
9478  }
9479
9480  /**
9481   * @param {string|Array.<Element>|Element|Node} selector
9482   * @param {string|Array.<Element>|Element|Node=} opt_root
9483   * @return {Array.<Element>}
9484   */
9485  function qwery(selector, opt_root) {
9486    var m, root = normalizeRoot(opt_root)
9487    if (!root || !selector) return []
9488    if (selector === win || isNode(selector)) {
9489      return !opt_root || (selector !== win && isNode(root) && isAncestor(selector, root)) ? [selector] : []
9490    }
9491    if (selector && arrayLike(selector)) return flatten(selector)
9492
9493
9494    if (doc.getElementsByClassName && selector == 'string' && (m = selector.match(classOnly))) {
9495      return toArray((root).getElementsByClassName(m[1]))
9496    }
9497    // using duck typing for 'a' window or 'a' document (not 'the' window || document)
9498    if (selector && (selector.document || (selector.nodeType && selector.nodeType == 9))) {
9499      return !opt_root ? [selector] : []
9500    }
9501    return toArray((root).querySelectorAll(selector))
9502  }
9503
9504  qwery.uniq = uniq
9505
9506  return qwery
9507}, this);
9508
9509},{}],48:[function(require,module,exports){
9510var inherits = require('inherits')
9511var EventEmitter = require('events').EventEmitter
9512var now = require('right-now')
9513var raf = require('raf')
9514
9515module.exports = Engine
9516function Engine(fn) {
9517    if (!(this instanceof Engine)) 
9518        return new Engine(fn)
9519    this.running = false
9520    this.last = now()
9521    this._frame = 0
9522    this._tick = this.tick.bind(this)
9523
9524    if (fn)
9525        this.on('tick', fn)
9526}
9527
9528inherits(Engine, EventEmitter)
9529
9530Engine.prototype.start = function() {
9531    if (this.running) 
9532        return
9533    this.running = true
9534    this.last = now()
9535    this._frame = raf(this._tick)
9536    return this
9537}
9538
9539Engine.prototype.stop = function() {
9540    this.running = false
9541    if (this._frame !== 0)
9542        raf.cancel(this._frame)
9543    this._frame = 0
9544    return this
9545}
9546
9547Engine.prototype.tick = function() {
9548    this._frame = raf(this._tick)
9549    var time = now()
9550    var dt = time - this.last
9551    this.emit('tick', dt)
9552    this.last = time
9553}
9554},{"events":43,"inherits":44,"raf":49,"right-now":51}],49:[function(require,module,exports){
9555(function (global){
9556var now = require('performance-now')
9557  , root = typeof window === 'undefined' ? global : window
9558  , vendors = ['moz', 'webkit']
9559  , suffix = 'AnimationFrame'
9560  , raf = root['request' + suffix]
9561  , caf = root['cancel' + suffix] || root['cancelRequest' + suffix]
9562
9563for(var i = 0; !raf && i < vendors.length; i++) {
9564  raf = root[vendors[i] + 'Request' + suffix]
9565  caf = root[vendors[i] + 'Cancel' + suffix]
9566      || root[vendors[i] + 'CancelRequest' + suffix]
9567}
9568
9569// Some versions of FF have rAF but not cAF
9570if(!raf || !caf) {
9571  var last = 0
9572    , id = 0
9573    , queue = []
9574    , frameDuration = 1000 / 60
9575
9576  raf = function(callback) {
9577    if(queue.length === 0) {
9578      var _now = now()
9579        , next = Math.max(0, frameDuration - (_now - last))
9580      last = next + _now
9581      setTimeout(function() {
9582        var cp = queue.slice(0)
9583        // Clear queue here to prevent
9584        // callbacks from appending listeners
9585        // to the current frame's queue
9586        queue.length = 0
9587        for(var i = 0; i < cp.length; i++) {
9588          if(!cp[i].cancelled) {
9589            try{
9590              cp[i].callback(last)
9591            } catch(e) {
9592              setTimeout(function() { throw e }, 0)
9593            }
9594          }
9595        }
9596      }, Math.round(next))
9597    }
9598    queue.push({
9599      handle: ++id,
9600      callback: callback,
9601      cancelled: false
9602    })
9603    return id
9604  }
9605
9606  caf = function(handle) {
9607    for(var i = 0; i < queue.length; i++) {
9608      if(queue[i].handle === handle) {
9609        queue[i].cancelled = true
9610      }
9611    }
9612  }
9613}
9614
9615module.exports = function(fn) {
9616  // Wrap in a new function to prevent
9617  // `cancel` potentially being assigned
9618  // to the native rAF function
9619  return raf.call(root, fn)
9620}
9621module.exports.cancel = function() {
9622  caf.apply(root, arguments)
9623}
9624module.exports.polyfill = function(object) {
9625  if (!object) {
9626    object = root;
9627  }
9628  object.requestAnimationFrame = raf
9629  object.cancelAnimationFrame = caf
9630}
9631
9632}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
9633},{"performance-now":50}],50:[function(require,module,exports){
9634(function (process){
9635// Generated by CoffeeScript 1.12.2
9636(function() {
9637  var getNanoSeconds, hrtime, loadTime, moduleLoadTime, nodeLoadTime, upTime;
9638
9639  if ((typeof performance !== "undefined" && performance !== null) && performance.now) {
9640    module.exports = function() {
9641      return performance.now();
9642    };
9643  } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) {
9644    module.exports = function() {
9645      return (getNanoSeconds() - nodeLoadTime) / 1e6;
9646    };
9647    hrtime = process.hrtime;
9648    getNanoSeconds = function() {
9649      var hr;
9650      hr = hrtime();
9651      return hr[0] * 1e9 + hr[1];
9652    };
9653    moduleLoadTime = getNanoSeconds();
9654    upTime = process.uptime() * 1e9;
9655    nodeLoadTime = moduleLoadTime - upTime;
9656  } else if (Date.now) {
9657    module.exports = function() {
9658      return Date.now() - loadTime;
9659    };
9660    loadTime = Date.now();
9661  } else {
9662    module.exports = function() {
9663      return new Date().getTime() - loadTime;
9664    };
9665    loadTime = new Date().getTime();
9666  }
9667
9668}).call(this);
9669
9670
9671
9672}).call(this,require('_process'))
9673},{"_process":46}],51:[function(require,module,exports){
9674(function (global){
9675module.exports =
9676  global.performance &&
9677  global.performance.now ? function now() {
9678    return performance.now()
9679  } : Date.now || function now() {
9680    return +new Date
9681  }
9682
9683}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
9684},{}],52:[function(require,module,exports){
9685(function (global){
9686!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.routes=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
9687
9688var localRoutes = [];
9689
9690
9691/**
9692 * Convert path to route object
9693 *
9694 * A string or RegExp should be passed,
9695 * will return { re, src, keys} obj
9696 *
9697 * @param  {String / RegExp} path
9698 * @return {Object}
9699 */
9700
9701var Route = function(path){
9702  //using 'new' is optional
9703
9704  var src, re, keys = [];
9705
9706  if(path instanceof RegExp){
9707    re = path;
9708    src = path.toString();
9709  }else{
9710    re = pathToRegExp(path, keys);
9711    src = path;
9712  }
9713
9714  return {
9715  	 re: re,
9716  	 src: path.toString(),
9717  	 keys: keys
9718  }
9719};
9720
9721/**
9722 * Normalize the given path string,
9723 * returning a regular expression.
9724 *
9725 * An empty array should be passed,
9726 * which will contain the placeholder
9727 * key names. For example "/user/:id" will
9728 * then contain ["id"].
9729 *
9730 * @param  {String} path
9731 * @param  {Array} keys
9732 * @return {RegExp}
9733 */
9734var pathToRegExp = function (path, keys) {
9735	path = path
9736		.concat('/?')
9737		.replace(/\/\(/g, '(?:/')
9738		.replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?|\*/g, function(_, slash, format, key, capture, optional){
9739			if (_ === "*"){
9740				keys.push(undefined);
9741				return _;
9742			}
9743
9744			keys.push(key);
9745			slash = slash || '';
9746			return ''
9747				+ (optional ? '' : slash)
9748				+ '(?:'
9749				+ (optional ? slash : '')
9750				+ (format || '') + (capture || '([^/]+?)') + ')'
9751				+ (optional || '');
9752		})
9753		.replace(/([\/.])/g, '\\$1')
9754		.replace(/\*/g, '(.*)');
9755	return new RegExp('^' + path + '$', 'i');
9756};
9757
9758/**
9759 * Attempt to match the given request to
9760 * one of the routes. When successful
9761 * a  {fn, params, splats} obj is returned
9762 *
9763 * @param  {Array} routes
9764 * @param  {String} uri
9765 * @return {Object}
9766 */
9767var match = function (routes, uri, startAt) {
9768	var captures, i = startAt || 0;
9769
9770	for (var len = routes.length; i < len; ++i) {
9771		var route = routes[i],
9772		    re = route.re,
9773		    keys = route.keys,
9774		    splats = [],
9775		    params = {};
9776
9777		if (captures = uri.match(re)) {
9778			for (var j = 1, len = captures.length; j < len; ++j) {
9779				var key = keys[j-1],
9780					val = typeof captures[j] === 'string'
9781						? unescape(captures[j])
9782						: captures[j];
9783				if (key) {
9784					params[key] = val;
9785				} else {
9786					splats.push(val);
9787				}
9788			}
9789			return {
9790				params: params,
9791				splats: splats,
9792				route: route.src,
9793				next: i + 1
9794			};
9795		}
9796	}
9797};
9798
9799/**
9800 * Default "normal" router constructor.
9801 * accepts path, fn tuples via addRoute
9802 * returns {fn, params, splats, route}
9803 *  via match
9804 *
9805 * @return {Object}
9806 */
9807
9808var Router = function(){
9809  //using 'new' is optional
9810  return {
9811    routes: [],
9812    routeMap : {},
9813    addRoute: function(path, fn){
9814      if (!path) throw new Error(' route requires a path');
9815      if (!fn) throw new Error(' route ' + path.toString() + ' requires a callback');
9816
9817      if (this.routeMap[path]) {
9818        throw new Error('path is already defined: ' + path);
9819      }
9820
9821      var route = Route(path);
9822      route.fn = fn;
9823
9824      this.routes.push(route);
9825      this.routeMap[path] = fn;
9826    },
9827
9828    removeRoute: function(path) {
9829      if (!path) throw new Error(' route requires a path');
9830      if (!this.routeMap[path]) {
9831        throw new Error('path does not exist: ' + path);
9832      }
9833
9834      var match;
9835      var newRoutes = [];
9836
9837      // copy the routes excluding the route being removed
9838      for (var i = 0; i < this.routes.length; i++) {
9839        var route = this.routes[i];
9840        if (route.src !== path) {
9841          newRoutes.push(route);
9842        }
9843      }
9844      this.routes = newRoutes;
9845      delete this.routeMap[path];
9846    },
9847
9848    match: function(pathname, startAt){
9849      var route = match(this.routes, pathname, startAt);
9850      if(route){
9851        route.fn = this.routeMap[route.route];
9852        route.next = this.match.bind(this, pathname, route.next)
9853      }
9854      return route;
9855    }
9856  }
9857};
9858
9859Router.Route = Route
9860Router.pathToRegExp = pathToRegExp
9861Router.match = match
9862// back compat
9863Router.Router = Router
9864
9865module.exports = Router
9866
9867},{}]},{},[1])
9868(1)
9869});
9870}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
9871},{}],53
vendor: 52,962 bytes, lines 9871-11421
9871:[function(require,module,exports){
9872//     Underscore.js 1.8.3
9873//     http://underscorejs.org
9874//     (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
9875//     Underscore may be freely distributed under the MIT license.
9876
9877(function() {
9878
9879  // Baseline setup
9880  // --------------
9881
9882  // Establish the root object, `window` in the browser, or `exports` on the server.
9883  var root = this;
9884
9885  // Save the previous value of the `_` variable.
9886  var previousUnderscore = root._;
9887
9888  // Save bytes in the minified (but not gzipped) version:
9889  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
9890
9891  // Create quick reference variables for speed access to core prototypes.
9892  var
9893    push             = ArrayProto.push,
9894    slice            = ArrayProto.slice,
9895    toString         = ObjProto.toString,
9896    hasOwnProperty   = ObjProto.hasOwnProperty;
9897
9898  // All **ECMAScript 5** native function implementations that we hope to use
9899  // are declared here.
9900  var
9901    nativeIsArray      = Array.isArray,
9902    nativeKeys         = Object.keys,
9903    nativeBind         = FuncProto.bind,
9904    nativeCreate       = Object.create;
9905
9906  // Naked function reference for surrogate-prototype-swapping.
9907  var Ctor = function(){};
9908
9909  // Create a safe reference to the Underscore object for use below.
9910  var _ = function(obj) {
9911    if (obj instanceof _) return obj;
9912    if (!(this instanceof _)) return new _(obj);
9913    this._wrapped = obj;
9914  };
9915
9916  // Export the Underscore object for **Node.js**, with
9917  // backwards-compatibility for the old `require()` API. If we're in
9918  // the browser, add `_` as a global object.
9919  if (typeof exports !== 'undefined') {
9920    if (typeof module !== 'undefined' && module.exports) {
9921      exports = module.exports = _;
9922    }
9923    exports._ = _;
9924  } else {
9925    root._ = _;
9926  }
9927
9928  // Current version.
9929  _.VERSION = '1.8.3';
9930
9931  // Internal function that returns an efficient (for current engines) version
9932  // of the passed-in callback, to be repeatedly applied in other Underscore
9933  // functions.
9934  var optimizeCb = function(func, context, argCount) {
9935    if (context === void 0) return func;
9936    switch (argCount == null ? 3 : argCount) {
9937      case 1: return function(value) {
9938        return func.call(context, value);
9939      };
9940      case 2: return function(value, other) {
9941        return func.call(context, value, other);
9942      };
9943      case 3: return function(value, index, collection) {
9944        return func.call(context, value, index, collection);
9945      };
9946      case 4: return function(accumulator, value, index, collection) {
9947        return func.call(context, accumulator, value, index, collection);
9948      };
9949    }
9950    return function() {
9951      return func.apply(context, arguments);
9952    };
9953  };
9954
9955  // A mostly-internal function to generate callbacks that can be applied
9956  // to each element in a collection, returning the desired result — either
9957  // identity, an arbitrary callback, a property matcher, or a property accessor.
9958  var cb = function(value, context, argCount) {
9959    if (value == null) return _.identity;
9960    if (_.isFunction(value)) return optimizeCb(value, context, argCount);
9961    if (_.isObject(value)) return _.matcher(value);
9962    return _.property(value);
9963  };
9964  _.iteratee = function(value, context) {
9965    return cb(value, context, Infinity);
9966  };
9967
9968  // An internal function for creating assigner functions.
9969  var createAssigner = function(keysFunc, undefinedOnly) {
9970    return function(obj) {
9971      var length = arguments.length;
9972      if (length < 2 || obj == null) return obj;
9973      for (var index = 1; index < length; index++) {
9974        var source = arguments[index],
9975            keys = keysFunc(source),
9976            l = keys.length;
9977        for (var i = 0; i < l; i++) {
9978          var key = keys[i];
9979          if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
9980        }
9981      }
9982      return obj;
9983    };
9984  };
9985
9986  // An internal function for creating a new object that inherits from another.
9987  var baseCreate = function(prototype) {
9988    if (!_.isObject(prototype)) return {};
9989    if (nativeCreate) return nativeCreate(prototype);
9990    Ctor.prototype = prototype;
9991    var result = new Ctor;
9992    Ctor.prototype = null;
9993    return result;
9994  };
9995
9996  var property = function(key) {
9997    return function(obj) {
9998      return obj == null ? void 0 : obj[key];
9999    };
10000  };
10001
10002  // Helper for collection methods to determine whether a collection
10003  // should be iterated as an array or as an object
10004  // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
10005  // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
10006  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
10007  var getLength = property('length');
10008  var isArrayLike = function(collection) {
10009    var length = getLength(collection);
10010    return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
10011  };
10012
10013  // Collection Functions
10014  // --------------------
10015
10016  // The cornerstone, an `each` implementation, aka `forEach`.
10017  // Handles raw objects in addition to array-likes. Treats all
10018  // sparse array-likes as if they were dense.
10019  _.each = _.forEach = function(obj, iteratee, context) {
10020    iteratee = optimizeCb(iteratee, context);
10021    var i, length;
10022    if (isArrayLike(obj)) {
10023      for (i = 0, length = obj.length; i < length; i++) {
10024        iteratee(obj[i], i, obj);
10025      }
10026    } else {
10027      var keys = _.keys(obj);
10028      for (i = 0, length = keys.length; i < length; i++) {
10029        iteratee(obj[keys[i]], keys[i], obj);
10030      }
10031    }
10032    return obj;
10033  };
10034
10035  // Return the results of applying the iteratee to each element.
10036  _.map = _.collect = function(obj, iteratee, context) {
10037    iteratee = cb(iteratee, context);
10038    var keys = !isArrayLike(obj) && _.keys(obj),
10039        length = (keys || obj).length,
10040        results = Array(length);
10041    for (var index = 0; index < length; index++) {
10042      var currentKey = keys ? keys[index] : index;
10043      results[index] = iteratee(obj[currentKey], currentKey, obj);
10044    }
10045    return results;
10046  };
10047
10048  // Create a reducing function iterating left or right.
10049  function createReduce(dir) {
10050    // Optimized iterator function as using arguments.length
10051    // in the main function will deoptimize the, see #1991.
10052    function iterator(obj, iteratee, memo, keys, index, length) {
10053      for (; index >= 0 && index < length; index += dir) {
10054        var currentKey = keys ? keys[index] : index;
10055        memo = iteratee(memo, obj[currentKey], currentKey, obj);
10056      }
10057      return memo;
10058    }
10059
10060    return function(obj, iteratee, memo, context) {
10061      iteratee = optimizeCb(iteratee, context, 4);
10062      var keys = !isArrayLike(obj) && _.keys(obj),
10063          length = (keys || obj).length,
10064          index = dir > 0 ? 0 : length - 1;
10065      // Determine the initial value if none is provided.
10066      if (arguments.length < 3) {
10067        memo = obj[keys ? keys[index] : index];
10068        index += dir;
10069      }
10070      return iterator(obj, iteratee, memo, keys, index, length);
10071    };
10072  }
10073
10074  // **Reduce** builds up a single result from a list of values, aka `inject`,
10075  // or `foldl`.
10076  _.reduce = _.foldl = _.inject = createReduce(1);
10077
10078  // The right-associative version of reduce, also known as `foldr`.
10079  _.reduceRight = _.foldr = createReduce(-1);
10080
10081  // Return the first value which passes a truth test. Aliased as `detect`.
10082  _.find = _.detect = function(obj, predicate, context) {
10083    var key;
10084    if (isArrayLike(obj)) {
10085      key = _.findIndex(obj, predicate, context);
10086    } else {
10087      key = _.findKey(obj, predicate, context);
10088    }
10089    if (key !== void 0 && key !== -1) return obj[key];
10090  };
10091
10092  // Return all the elements that pass a truth test.
10093  // Aliased as `select`.
10094  _.filter = _.select = function(obj, predicate, context) {
10095    var results = [];
10096    predicate = cb(predicate, context);
10097    _.each(obj, function(value, index, list) {
10098      if (predicate(value, index, list)) results.push(value);
10099    });
10100    return results;
10101  };
10102
10103  // Return all the elements for which a truth test fails.
10104  _.reject = function(obj, predicate, context) {
10105    return _.filter(obj, _.negate(cb(predicate)), context);
10106  };
10107
10108  // Determine whether all of the elements match a truth test.
10109  // Aliased as `all`.
10110  _.every = _.all = function(obj, predicate, context) {
10111    predicate = cb(predicate, context);
10112    var keys = !isArrayLike(obj) && _.keys(obj),
10113        length = (keys || obj).length;
10114    for (var index = 0; index < length; index++) {
10115      var currentKey = keys ? keys[index] : index;
10116      if (!predicate(obj[currentKey], currentKey, obj)) return false;
10117    }
10118    return true;
10119  };
10120
10121  // Determine if at least one element in the object matches a truth test.
10122  // Aliased as `any`.
10123  _.some = _.any = function(obj, predicate, context) {
10124    predicate = cb(predicate, context);
10125    var keys = !isArrayLike(obj) && _.keys(obj),
10126        length = (keys || obj).length;
10127    for (var index = 0; index < length; index++) {
10128      var currentKey = keys ? keys[index] : index;
10129      if (predicate(obj[currentKey], currentKey, obj)) return true;
10130    }
10131    return false;
10132  };
10133
10134  // Determine if the array or object contains a given item (using `===`).
10135  // Aliased as `includes` and `include`.
10136  _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
10137    if (!isArrayLike(obj)) obj = _.values(obj);
10138    if (typeof fromIndex != 'number' || guard) fromIndex = 0;
10139    return _.indexOf(obj, item, fromIndex) >= 0;
10140  };
10141
10142  // Invoke a method (with arguments) on every item in a collection.
10143  _.invoke = function(obj, method) {
10144    var args = slice.call(arguments, 2);
10145    var isFunc = _.isFunction(method);
10146    return _.map(obj, function(value) {
10147      var func = isFunc ? method : value[method];
10148      return func == null ? func : func.apply(value, args);
10149    });
10150  };
10151
10152  // Convenience version of a common use case of `map`: fetching a property.
10153  _.pluck = function(obj, key) {
10154    return _.map(obj, _.property(key));
10155  };
10156
10157  // Convenience version of a common use case of `filter`: selecting only objects
10158  // containing specific `key:value` pairs.
10159  _.where = function(obj, attrs) {
10160    return _.filter(obj, _.matcher(attrs));
10161  };
10162
10163  // Convenience version of a common use case of `find`: getting the first object
10164  // containing specific `key:value` pairs.
10165  _.findWhere = function(obj, attrs) {
10166    return _.find(obj, _.matcher(attrs));
10167  };
10168
10169  // Return the maximum element (or element-based computation).
10170  _.max = function(obj, iteratee, context) {
10171    var result = -Infinity, lastComputed = -Infinity,
10172        value, computed;
10173    if (iteratee == null && obj != null) {
10174      obj = isArrayLike(obj) ? obj : _.values(obj);
10175      for (var i = 0, length = obj.length; i < length; i++) {
10176        value = obj[i];
10177        if (value > result) {
10178          result = value;
10179        }
10180      }
10181    } else {
10182      iteratee = cb(iteratee, context);
10183      _.each(obj, function(value, index, list) {
10184        computed = iteratee(value, index, list);
10185        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
10186          result = value;
10187          lastComputed = computed;
10188        }
10189      });
10190    }
10191    return result;
10192  };
10193
10194  // Return the minimum element (or element-based computation).
10195  _.min = function(obj, iteratee, context) {
10196    var result = Infinity, lastComputed = Infinity,
10197        value, computed;
10198    if (iteratee == null && obj != null) {
10199      obj = isArrayLike(obj) ? obj : _.values(obj);
10200      for (var i = 0, length = obj.length; i < length; i++) {
10201        value = obj[i];
10202        if (value < result) {
10203          result = value;
10204        }
10205      }
10206    } else {
10207      iteratee = cb(iteratee, context);
10208      _.each(obj, function(value, index, list) {
10209        computed = iteratee(value, index, list);
10210        if (computed < lastComputed || computed === Infinity && result === Infinity) {
10211          result = value;
10212          lastComputed = computed;
10213        }
10214      });
10215    }
10216    return result;
10217  };
10218
10219  // Shuffle a collection, using the modern version of the
10220  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
10221  _.shuffle = function(obj) {
10222    var set = isArrayLike(obj) ? obj : _.values(obj);
10223    var length = set.length;
10224    var shuffled = Array(length);
10225    for (var index = 0, rand; index < length; index++) {
10226      rand = _.random(0, index);
10227      if (rand !== index) shuffled[index] = shuffled[rand];
10228      shuffled[rand] = set[index];
10229    }
10230    return shuffled;
10231  };
10232
10233  // Sample **n** random values from a collection.
10234  // If **n** is not specified, returns a single random element.
10235  // The internal `guard` argument allows it to work with `map`.
10236  _.sample = function(obj, n, guard) {
10237    if (n == null || guard) {
10238      if (!isArrayLike(obj)) obj = _.values(obj);
10239      return obj[_.random(obj.length - 1)];
10240    }
10241    return _.shuffle(obj).slice(0, Math.max(0, n));
10242  };
10243
10244  // Sort the object's values by a criterion produced by an iteratee.
10245  _.sortBy = function(obj, iteratee, context) {
10246    iteratee = cb(iteratee, context);
10247    return _.pluck(_.map(obj, function(value, index, list) {
10248      return {
10249        value: value,
10250        index: index,
10251        criteria: iteratee(value, index, list)
10252      };
10253    }).sort(function(left, right) {
10254      var a = left.criteria;
10255      var b = right.criteria;
10256      if (a !== b) {
10257        if (a > b || a === void 0) return 1;
10258        if (a < b || b === void 0) return -1;
10259      }
10260      return left.index - right.index;
10261    }), 'value');
10262  };
10263
10264  // An internal function used for aggregate "group by" operations.
10265  var group = function(behavior) {
10266    return function(obj, iteratee, context) {
10267      var result = {};
10268      iteratee = cb(iteratee, context);
10269      _.each(obj, function(value, index) {
10270        var key = iteratee(value, index, obj);
10271        behavior(result, value, key);
10272      });
10273      return result;
10274    };
10275  };
10276
10277  // Groups the object's values by a criterion. Pass either a string attribute
10278  // to group by, or a function that returns the criterion.
10279  _.groupBy = group(function(result, value, key) {
10280    if (_.has(result, key)) result[key].push(value); else result[key] = [value];
10281  });
10282
10283  // Indexes the object's values by a criterion, similar to `groupBy`, but for
10284  // when you know that your index values will be unique.
10285  _.indexBy = group(function(result, value, key) {
10286    result[key] = value;
10287  });
10288
10289  // Counts instances of an object that group by a certain criterion. Pass
10290  // either a string attribute to count by, or a function that returns the
10291  // criterion.
10292  _.countBy = group(function(result, value, key) {
10293    if (_.has(result, key)) result[key]++; else result[key] = 1;
10294  });
10295
10296  // Safely create a real, live array from anything iterable.
10297  _.toArray = function(obj) {
10298    if (!obj) return [];
10299    if (_.isArray(obj)) return slice.call(obj);
10300    if (isArrayLike(obj)) return _.map(obj, _.identity);
10301    return _.values(obj);
10302  };
10303
10304  // Return the number of elements in an object.
10305  _.size = function(obj) {
10306    if (obj == null) return 0;
10307    return isArrayLike(obj) ? obj.length : _.keys(obj).length;
10308  };
10309
10310  // Split a collection into two arrays: one whose elements all satisfy the given
10311  // predicate, and one whose elements all do not satisfy the predicate.
10312  _.partition = function(obj, predicate, context) {
10313    predicate = cb(predicate, context);
10314    var pass = [], fail = [];
10315    _.each(obj, function(value, key, obj) {
10316      (predicate(value, key, obj) ? pass : fail).push(value);
10317    });
10318    return [pass, fail];
10319  };
10320
10321  // Array Functions
10322  // ---------------
10323
10324  // Get the first element of an array. Passing **n** will return the first N
10325  // values in the array. Aliased as `head` and `take`. The **guard** check
10326  // allows it to work with `_.map`.
10327  _.first = _.head = _.take = function(array, n, guard) {
10328    if (array == null) return void 0;
10329    if (n == null || guard) return array[0];
10330    return _.initial(array, array.length - n);
10331  };
10332
10333  // Returns everything but the last entry of the array. Especially useful on
10334  // the arguments object. Passing **n** will return all the values in
10335  // the array, excluding the last N.
10336  _.initial = function(array, n, guard) {
10337    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
10338  };
10339
10340  // Get the last element of an array. Passing **n** will return the last N
10341  // values in the array.
10342  _.last = function(array, n, guard) {
10343    if (array == null) return void 0;
10344    if (n == null || guard) return array[array.length - 1];
10345    return _.rest(array, Math.max(0, array.length - n));
10346  };
10347
10348  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
10349  // Especially useful on the arguments object. Passing an **n** will return
10350  // the rest N values in the array.
10351  _.rest = _.tail = _.drop = function(array, n, guard) {
10352    return slice.call(array, n == null || guard ? 1 : n);
10353  };
10354
10355  // Trim out all falsy values from an array.
10356  _.compact = function(array) {
10357    return _.filter(array, _.identity);
10358  };
10359
10360  // Internal implementation of a recursive `flatten` function.
10361  var flatten = function(input, shallow, strict, startIndex) {
10362    var output = [], idx = 0;
10363    for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
10364      var value = input[i];
10365      if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
10366        //flatten current level of array or arguments object
10367        if (!shallow) value = flatten(value, shallow, strict);
10368        var j = 0, len = value.length;
10369        output.length += len;
10370        while (j < len) {
10371          output[idx++] = value[j++];
10372        }
10373      } else if (!strict) {
10374        output[idx++] = value;
10375      }
10376    }
10377    return output;
10378  };
10379
10380  // Flatten out an array, either recursively (by default), or just one level.
10381  _.flatten = function(array, shallow) {
10382    return flatten(array, shallow, false);
10383  };
10384
10385  // Return a version of the array that does not contain the specified value(s).
10386  _.without = function(array) {
10387    return _.difference(array, slice.call(arguments, 1));
10388  };
10389
10390  // Produce a duplicate-free version of the array. If the array has already
10391  // been sorted, you have the option of using a faster algorithm.
10392  // Aliased as `unique`.
10393  _.uniq = _.unique = function(array, isSorted, iteratee, context) {
10394    if (!_.isBoolean(isSorted)) {
10395      context = iteratee;
10396      iteratee = isSorted;
10397      isSorted = false;
10398    }
10399    if (iteratee != null) iteratee = cb(iteratee, context);
10400    var result = [];
10401    var seen = [];
10402    for (var i = 0, length = getLength(array); i < length; i++) {
10403      var value = array[i],
10404          computed = iteratee ? iteratee(value, i, array) : value;
10405      if (isSorted) {
10406        if (!i || seen !== computed) result.push(value);
10407        seen = computed;
10408      } else if (iteratee) {
10409        if (!_.contains(seen, computed)) {
10410          seen.push(computed);
10411          result.push(value);
10412        }
10413      } else if (!_.contains(result, value)) {
10414        result.push(value);
10415      }
10416    }
10417    return result;
10418  };
10419
10420  // Produce an array that contains the union: each distinct element from all of
10421  // the passed-in arrays.
10422  _.union = function() {
10423    return _.uniq(flatten(arguments, true, true));
10424  };
10425
10426  // Produce an array that contains every item shared between all the
10427  // passed-in arrays.
10428  _.intersection = function(array) {
10429    var result = [];
10430    var argsLength = arguments.length;
10431    for (var i = 0, length = getLength(array); i < length; i++) {
10432      var item = array[i];
10433      if (_.contains(result, item)) continue;
10434      for (var j = 1; j < argsLength; j++) {
10435        if (!_.contains(arguments[j], item)) break;
10436      }
10437      if (j === argsLength) result.push(item);
10438    }
10439    return result;
10440  };
10441
10442  // Take the difference between one array and a number of other arrays.
10443  // Only the elements present in just the first array will remain.
10444  _.difference = function(array) {
10445    var rest = flatten(arguments, true, true, 1);
10446    return _.filter(array, function(value){
10447      return !_.contains(rest, value);
10448    });
10449  };
10450
10451  // Zip together multiple lists into a single array -- elements that share
10452  // an index go together.
10453  _.zip = function() {
10454    return _.unzip(arguments);
10455  };
10456
10457  // Complement of _.zip. Unzip accepts an array of arrays and groups
10458  // each array's elements on shared indices
10459  _.unzip = function(array) {
10460    var length = array && _.max(array, getLength).length || 0;
10461    var result = Array(length);
10462
10463    for (var index = 0; index < length; index++) {
10464      result[index] = _.pluck(array, index);
10465    }
10466    return result;
10467  };
10468
10469  // Converts lists into objects. Pass either a single array of `[key, value]`
10470  // pairs, or two parallel arrays of the same length -- one of keys, and one of
10471  // the corresponding values.
10472  _.object = function(list, values) {
10473    var result = {};
10474    for (var i = 0, length = getLength(list); i < length; i++) {
10475      if (values) {
10476        result[list[i]] = values[i];
10477      } else {
10478        result[list[i][0]] = list[i][1];
10479      }
10480    }
10481    return result;
10482  };
10483
10484  // Generator function to create the findIndex and findLastIndex functions
10485  function createPredicateIndexFinder(dir) {
10486    return function(array, predicate, context) {
10487      predicate = cb(predicate, context);
10488      var length = getLength(array);
10489      var index = dir > 0 ? 0 : length - 1;
10490      for (; index >= 0 && index < length; index += dir) {
10491        if (predicate(array[index], index, array)) return index;
10492      }
10493      return -1;
10494    };
10495  }
10496
10497  // Returns the first index on an array-like that passes a predicate test
10498  _.findIndex = createPredicateIndexFinder(1);
10499  _.findLastIndex = createPredicateIndexFinder(-1);
10500
10501  // Use a comparator function to figure out the smallest index at which
10502  // an object should be inserted so as to maintain order. Uses binary search.
10503  _.sortedIndex = function(array, obj, iteratee, context) {
10504    iteratee = cb(iteratee, context, 1);
10505    var value = iteratee(obj);
10506    var low = 0, high = getLength(array);
10507    while (low < high) {
10508      var mid = Math.floor((low + high) / 2);
10509      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
10510    }
10511    return low;
10512  };
10513
10514  // Generator function to create the indexOf and lastIndexOf functions
10515  function createIndexFinder(dir, predicateFind, sortedIndex) {
10516    return function(array, item, idx) {
10517      var i = 0, length = getLength(array);
10518      if (typeof idx == 'number') {
10519        if (dir > 0) {
10520            i = idx >= 0 ? idx : Math.max(idx + length, i);
10521        } else {
10522            length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
10523        }
10524      } else if (sortedIndex && idx && length) {
10525        idx = sortedIndex(array, item);
10526        return array[idx] === item ? idx : -1;
10527      }
10528      if (item !== item) {
10529        idx = predicateFind(slice.call(array, i, length), _.isNaN);
10530        return idx >= 0 ? idx + i : -1;
10531      }
10532      for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
10533        if (array[idx] === item) return idx;
10534      }
10535      return -1;
10536    };
10537  }
10538
10539  // Return the position of the first occurrence of an item in an array,
10540  // or -1 if the item is not included in the array.
10541  // If the array is large and already in sort order, pass `true`
10542  // for **isSorted** to use binary search.
10543  _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
10544  _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
10545
10546  // Generate an integer Array containing an arithmetic progression. A port of
10547  // the native Python `range()` function. See
10548  // [the Python documentation](http://docs.python.org/library/functions.html#range).
10549  _.range = function(start, stop, step) {
10550    if (stop == null) {
10551      stop = start || 0;
10552      start = 0;
10553    }
10554    step = step || 1;
10555
10556    var length = Math.max(Math.ceil((stop - start) / step), 0);
10557    var range = Array(length);
10558
10559    for (var idx = 0; idx < length; idx++, start += step) {
10560      range[idx] = start;
10561    }
10562
10563    return range;
10564  };
10565
10566  // Function (ahem) Functions
10567  // ------------------
10568
10569  // Determines whether to execute a function as a constructor
10570  // or a normal function with the provided arguments
10571  var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
10572    if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
10573    var self = baseCreate(sourceFunc.prototype);
10574    var result = sourceFunc.apply(self, args);
10575    if (_.isObject(result)) return result;
10576    return self;
10577  };
10578
10579  // Create a function bound to a given object (assigning `this`, and arguments,
10580  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
10581  // available.
10582  _.bind = function(func, context) {
10583    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
10584    if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
10585    var args = slice.call(arguments, 2);
10586    var bound = function() {
10587      return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
10588    };
10589    return bound;
10590  };
10591
10592  // Partially apply a function by creating a version that has had some of its
10593  // arguments pre-filled, without changing its dynamic `this` context. _ acts
10594  // as a placeholder, allowing any combination of arguments to be pre-filled.
10595  _.partial = function(func) {
10596    var boundArgs = slice.call(arguments, 1);
10597    var bound = function() {
10598      var position = 0, length = boundArgs.length;
10599      var args = Array(length);
10600      for (var i = 0; i < length; i++) {
10601        args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
10602      }
10603      while (position < arguments.length) args.push(arguments[position++]);
10604      return executeBound(func, bound, this, this, args);
10605    };
10606    return bound;
10607  };
10608
10609  // Bind a number of an object's methods to that object. Remaining arguments
10610  // are the method names to be bound. Useful for ensuring that all callbacks
10611  // defined on an object belong to it.
10612  _.bindAll = function(obj) {
10613    var i, length = arguments.length, key;
10614    if (length <= 1) throw new Error('bindAll must be passed function names');
10615    for (i = 1; i < length; i++) {
10616      key = arguments[i];
10617      obj[key] = _.bind(obj[key], obj);
10618    }
10619    return obj;
10620  };
10621
10622  // Memoize an expensive function by storing its results.
10623  _.memoize = function(func, hasher) {
10624    var memoize = function(key) {
10625      var cache = memoize.cache;
10626      var address = '' + (hasher ? hasher.apply(this, arguments) : key);
10627      if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
10628      return cache[address];
10629    };
10630    memoize.cache = {};
10631    return memoize;
10632  };
10633
10634  // Delays a function for the given number of milliseconds, and then calls
10635  // it with the arguments supplied.
10636  _.delay = function(func, wait) {
10637    var args = slice.call(arguments, 2);
10638    return setTimeout(function(){
10639      return func.apply(null, args);
10640    }, wait);
10641  };
10642
10643  // Defers a function, scheduling it to run after the current call stack has
10644  // cleared.
10645  _.defer = _.partial(_.delay, _, 1);
10646
10647  // Returns a function, that, when invoked, will only be triggered at most once
10648  // during a given window of time. Normally, the throttled function will run
10649  // as much as it can, without ever going more than once per `wait` duration;
10650  // but if you'd like to disable the execution on the leading edge, pass
10651  // `{leading: false}`. To disable execution on the trailing edge, ditto.
10652  _.throttle = function(func, wait, options) {
10653    var context, args, result;
10654    var timeout = null;
10655    var previous = 0;
10656    if (!options) options = {};
10657    var later = function() {
10658      previous = options.leading === false ? 0 : _.now();
10659      timeout = null;
10660      result = func.apply(context, args);
10661      if (!timeout) context = args = null;
10662    };
10663    return function() {
10664      var now = _.now();
10665      if (!previous && options.leading === false) previous = now;
10666      var remaining = wait - (now - previous);
10667      context = this;
10668      args = arguments;
10669      if (remaining <= 0 || remaining > wait) {
10670        if (timeout) {
10671          clearTimeout(timeout);
10672          timeout = null;
10673        }
10674        previous = now;
10675        result = func.apply(context, args);
10676        if (!timeout) context = args = null;
10677      } else if (!timeout && options.trailing !== false) {
10678        timeout = setTimeout(later, remaining);
10679      }
10680      return result;
10681    };
10682  };
10683
10684  // Returns a function, that, as long as it continues to be invoked, will not
10685  // be triggered. The function will be called after it stops being called for
10686  // N milliseconds. If `immediate` is passed, trigger the function on the
10687  // leading edge, instead of the trailing.
10688  _.debounce = function(func, wait, immediate) {
10689    var timeout, args, context, timestamp, result;
10690
10691    var later = function() {
10692      var last = _.now() - timestamp;
10693
10694      if (last < wait && last >= 0) {
10695        timeout = setTimeout(later, wait - last);
10696      } else {
10697        timeout = null;
10698        if (!immediate) {
10699          result = func.apply(context, args);
10700          if (!timeout) context = args = null;
10701        }
10702      }
10703    };
10704
10705    return function() {
10706      context = this;
10707      args = arguments;
10708      timestamp = _.now();
10709      var callNow = immediate && !timeout;
10710      if (!timeout) timeout = setTimeout(later, wait);
10711      if (callNow) {
10712        result = func.apply(context, args);
10713        context = args = null;
10714      }
10715
10716      return result;
10717    };
10718  };
10719
10720  // Returns the first function passed as an argument to the second,
10721  // allowing you to adjust arguments, run code before and after, and
10722  // conditionally execute the original function.
10723  _.wrap = function(func, wrapper) {
10724    return _.partial(wrapper, func);
10725  };
10726
10727  // Returns a negated version of the passed-in predicate.
10728  _.negate = function(predicate) {
10729    return function() {
10730      return !predicate.apply(this, arguments);
10731    };
10732  };
10733
10734  // Returns a function that is the composition of a list of functions, each
10735  // consuming the return value of the function that follows.
10736  _.compose = function() {
10737    var args = arguments;
10738    var start = args.length - 1;
10739    return function() {
10740      var i = start;
10741      var result = args[start].apply(this, arguments);
10742      while (i--) result = args[i].call(this, result);
10743      return result;
10744    };
10745  };
10746
10747  // Returns a function that will only be executed on and after the Nth call.
10748  _.after = function(times, func) {
10749    return function() {
10750      if (--times < 1) {
10751        return func.apply(this, arguments);
10752      }
10753    };
10754  };
10755
10756  // Returns a function that will only be executed up to (but not including) the Nth call.
10757  _.before = function(times, func) {
10758    var memo;
10759    return function() {
10760      if (--times > 0) {
10761        memo = func.apply(this, arguments);
10762      }
10763      if (times <= 1) func = null;
10764      return memo;
10765    };
10766  };
10767
10768  // Returns a function that will be executed at most one time, no matter how
10769  // often you call it. Useful for lazy initialization.
10770  _.once = _.partial(_.before, 2);
10771
10772  // Object Functions
10773  // ----------------
10774
10775  // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
10776  var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
10777  var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
10778                      'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
10779
10780  function collectNonEnumProps(obj, keys) {
10781    var nonEnumIdx = nonEnumerableProps.length;
10782    var constructor = obj.constructor;
10783    var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
10784
10785    // Constructor is a special case.
10786    var prop = 'constructor';
10787    if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
10788
10789    while (nonEnumIdx--) {
10790      prop = nonEnumerableProps[nonEnumIdx];
10791      if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
10792        keys.push(prop);
10793      }
10794    }
10795  }
10796
10797  // Retrieve the names of an object's own properties.
10798  // Delegates to **ECMAScript 5**'s native `Object.keys`
10799  _.keys = function(obj) {
10800    if (!_.isObject(obj)) return [];
10801    if (nativeKeys) return nativeKeys(obj);
10802    var keys = [];
10803    for (var key in obj) if (_.has(obj, key)) keys.push(key);
10804    // Ahem, IE < 9.
10805    if (hasEnumBug) collectNonEnumProps(obj, keys);
10806    return keys;
10807  };
10808
10809  // Retrieve all the property names of an object.
10810  _.allKeys = function(obj) {
10811    if (!_.isObject(obj)) return [];
10812    var keys = [];
10813    for (var key in obj) keys.push(key);
10814    // Ahem, IE < 9.
10815    if (hasEnumBug) collectNonEnumProps(obj, keys);
10816    return keys;
10817  };
10818
10819  // Retrieve the values of an object's properties.
10820  _.values = function(obj) {
10821    var keys = _.keys(obj);
10822    var length = keys.length;
10823    var values = Array(length);
10824    for (var i = 0; i < length; i++) {
10825      values[i] = obj[keys[i]];
10826    }
10827    return values;
10828  };
10829
10830  // Returns the results of applying the iteratee to each element of the object
10831  // In contrast to _.map it returns an object
10832  _.mapObject = function(obj, iteratee, context) {
10833    iteratee = cb(iteratee, context);
10834    var keys =  _.keys(obj),
10835          length = keys.length,
10836          results = {},
10837          currentKey;
10838      for (var index = 0; index < length; index++) {
10839        currentKey = keys[index];
10840        results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
10841      }
10842      return results;
10843  };
10844
10845  // Convert an object into a list of `[key, value]` pairs.
10846  _.pairs = function(obj) {
10847    var keys = _.keys(obj);
10848    var length = keys.length;
10849    var pairs = Array(length);
10850    for (var i = 0; i < length; i++) {
10851      pairs[i] = [keys[i], obj[keys[i]]];
10852    }
10853    return pairs;
10854  };
10855
10856  // Invert the keys and values of an object. The values must be serializable.
10857  _.invert = function(obj) {
10858    var result = {};
10859    var keys = _.keys(obj);
10860    for (var i = 0, length = keys.length; i < length; i++) {
10861      result[obj[keys[i]]] = keys[i];
10862    }
10863    return result;
10864  };
10865
10866  // Return a sorted list of the function names available on the object.
10867  // Aliased as `methods`
10868  _.functions = _.methods = function(obj) {
10869    var names = [];
10870    for (var key in obj) {
10871      if (_.isFunction(obj[key])) names.push(key);
10872    }
10873    return names.sort();
10874  };
10875
10876  // Extend a given object with all the properties in passed-in object(s).
10877  _.extend = createAssigner(_.allKeys);
10878
10879  // Assigns a given object with all the own properties in the passed-in object(s)
10880  // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
10881  _.extendOwn = _.assign = createAssigner(_.keys);
10882
10883  // Returns the first key on an object that passes a predicate test
10884  _.findKey = function(obj, predicate, context) {
10885    predicate = cb(predicate, context);
10886    var keys = _.keys(obj), key;
10887    for (var i = 0, length = keys.length; i < length; i++) {
10888      key = keys[i];
10889      if (predicate(obj[key], key, obj)) return key;
10890    }
10891  };
10892
10893  // Return a copy of the object only containing the whitelisted properties.
10894  _.pick = function(object, oiteratee, context) {
10895    var result = {}, obj = object, iteratee, keys;
10896    if (obj == null) return result;
10897    if (_.isFunction(oiteratee)) {
10898      keys = _.allKeys(obj);
10899      iteratee = optimizeCb(oiteratee, context);
10900    } else {
10901      keys = flatten(arguments, false, false, 1);
10902      iteratee = function(value, key, obj) { return key in obj; };
10903      obj = Object(obj);
10904    }
10905    for (var i = 0, length = keys.length; i < length; i++) {
10906      var key = keys[i];
10907      var value = obj[key];
10908      if (iteratee(value, key, obj)) result[key] = value;
10909    }
10910    return result;
10911  };
10912
10913   // Return a copy of the object without the blacklisted properties.
10914  _.omit = function(obj, iteratee, context) {
10915    if (_.isFunction(iteratee)) {
10916      iteratee = _.negate(iteratee);
10917    } else {
10918      var keys = _.map(flatten(arguments, false, false, 1), String);
10919      iteratee = function(value, key) {
10920        return !_.contains(keys, key);
10921      };
10922    }
10923    return _.pick(obj, iteratee, context);
10924  };
10925
10926  // Fill in a given object with default properties.
10927  _.defaults = createAssigner(_.allKeys, true);
10928
10929  // Creates an object that inherits from the given prototype object.
10930  // If additional properties are provided then they will be added to the
10931  // created object.
10932  _.create = function(prototype, props) {
10933    var result = baseCreate(prototype);
10934    if (props) _.extendOwn(result, props);
10935    return result;
10936  };
10937
10938  // Create a (shallow-cloned) duplicate of an object.
10939  _.clone = function(obj) {
10940    if (!_.isObject(obj)) return obj;
10941    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
10942  };
10943
10944  // Invokes interceptor with the obj, and then returns obj.
10945  // The primary purpose of this method is to "tap into" a method chain, in
10946  // order to perform operations on intermediate results within the chain.
10947  _.tap = function(obj, interceptor) {
10948    interceptor(obj);
10949    return obj;
10950  };
10951
10952  // Returns whether an object has a given set of `key:value` pairs.
10953  _.isMatch = function(object, attrs) {
10954    var keys = _.keys(attrs), length = keys.length;
10955    if (object == null) return !length;
10956    var obj = Object(object);
10957    for (var i = 0; i < length; i++) {
10958      var key = keys[i];
10959      if (attrs[key] !== obj[key] || !(key in obj)) return false;
10960    }
10961    return true;
10962  };
10963
10964
10965  // Internal recursive comparison function for `isEqual`.
10966  var eq = function(a, b, aStack, bStack) {
10967    // Identical objects are equal. `0 === -0`, but they aren't identical.
10968    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
10969    if (a === b) return a !== 0 || 1 / a === 1 / b;
10970    // A strict comparison is necessary because `null == undefined`.
10971    if (a == null || b == null) return a === b;
10972    // Unwrap any wrapped objects.
10973    if (a instanceof _) a = a._wrapped;
10974    if (b instanceof _) b = b._wrapped;
10975    // Compare `[[Class]]` names.
10976    var className = toString.call(a);
10977    if (className !== toString.call(b)) return false;
10978    switch (className) {
10979      // Strings, numbers, regular expressions, dates, and booleans are compared by value.
10980      case '[object RegExp]':
10981      // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
10982      case '[object String]':
10983        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
10984        // equivalent to `new String("5")`.
10985        return '' + a === '' + b;
10986      case '[object Number]':
10987        // `NaN`s are equivalent, but non-reflexive.
10988        // Object(NaN) is equivalent to NaN
10989        if (+a !== +a) return +b !== +b;
10990        // An `egal` comparison is performed for other numeric values.
10991        return +a === 0 ? 1 / +a === 1 / b : +a === +b;
10992      case '[object Date]':
10993      case '[object Boolean]':
10994        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
10995        // millisecond representations. Note that invalid dates with millisecond representations
10996        // of `NaN` are not equivalent.
10997        return +a === +b;
10998    }
10999
11000    var areArrays = className === '[object Array]';
11001    if (!areArrays) {
11002      if (typeof a != 'object' || typeof b != 'object') return false;
11003
11004      // Objects with different constructors are not equivalent, but `Object`s or `Array`s
11005      // from different frames are.
11006      var aCtor = a.constructor, bCtor = b.constructor;
11007      if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
11008                               _.isFunction(bCtor) && bCtor instanceof bCtor)
11009                          && ('constructor' in a && 'constructor' in b)) {
11010        return false;
11011      }
11012    }
11013    // Assume equality for cyclic structures. The algorithm for detecting cyclic
11014    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
11015
11016    // Initializing stack of traversed objects.
11017    // It's done here since we only need them for objects and arrays comparison.
11018    aStack = aStack || [];
11019    bStack = bStack || [];
11020    var length = aStack.length;
11021    while (length--) {
11022      // Linear search. Performance is inversely proportional to the number of
11023      // unique nested structures.
11024      if (aStack[length] === a) return bStack[length] === b;
11025    }
11026
11027    // Add the first object to the stack of traversed objects.
11028    aStack.push(a);
11029    bStack.push(b);
11030
11031    // Recursively compare objects and arrays.
11032    if (areArrays) {
11033      // Compare array lengths to determine if a deep comparison is necessary.
11034      length = a.length;
11035      if (length !== b.length) return false;
11036      // Deep compare the contents, ignoring non-numeric properties.
11037      while (length--) {
11038        if (!eq(a[length], b[length], aStack, bStack)) return false;
11039      }
11040    } else {
11041      // Deep compare objects.
11042      var keys = _.keys(a), key;
11043      length = keys.length;
11044      // Ensure that both objects contain the same number of properties before comparing deep equality.
11045      if (_.keys(b).length !== length) return false;
11046      while (length--) {
11047        // Deep compare each member
11048        key = keys[length];
11049        if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
11050      }
11051    }
11052    // Remove the first object from the stack of traversed objects.
11053    aStack.pop();
11054    bStack.pop();
11055    return true;
11056  };
11057
11058  // Perform a deep comparison to check if two objects are equal.
11059  _.isEqual = function(a, b) {
11060    return eq(a, b);
11061  };
11062
11063  // Is a given array, string, or object empty?
11064  // An "empty" object has no enumerable own-properties.
11065  _.isEmpty = function(obj) {
11066    if (obj == null) return true;
11067    if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
11068    return _.keys(obj).length === 0;
11069  };
11070
11071  // Is a given value a DOM element?
11072  _.isElement = function(obj) {
11073    return !!(obj && obj.nodeType === 1);
11074  };
11075
11076  // Is a given value an array?
11077  // Delegates to ECMA5's native Array.isArray
11078  _.isArray = nativeIsArray || function(obj) {
11079    return toString.call(obj) === '[object Array]';
11080  };
11081
11082  // Is a given variable an object?
11083  _.isObject = function(obj) {
11084    var type = typeof obj;
11085    return type === 'function' || type === 'object' && !!obj;
11086  };
11087
11088  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
11089  _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
11090    _['is' + name] = function(obj) {
11091      return toString.call(obj) === '[object ' + name + ']';
11092    };
11093  });
11094
11095  // Define a fallback version of the method in browsers (ahem, IE < 9), where
11096  // there isn't any inspectable "Arguments" type.
11097  if (!_.isArguments(arguments)) {
11098    _.isArguments = function(obj) {
11099      return _.has(obj, 'callee');
11100    };
11101  }
11102
11103  // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
11104  // IE 11 (#1621), and in Safari 8 (#1929).
11105  if (typeof /./ != 'function' && typeof Int8Array != 'object') {
11106    _.isFunction = function(obj) {
11107      return typeof obj == 'function' || false;
11108    };
11109  }
11110
11111  // Is a given object a finite number?
11112  _.isFinite = function(obj) {
11113    return isFinite(obj) && !isNaN(parseFloat(obj));
11114  };
11115
11116  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
11117  _.isNaN = function(obj) {
11118    return _.isNumber(obj) && obj !== +obj;
11119  };
11120
11121  // Is a given value a boolean?
11122  _.isBoolean = function(obj) {
11123    return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
11124  };
11125
11126  // Is a given value equal to null?
11127  _.isNull = function(obj) {
11128    return obj === null;
11129  };
11130
11131  // Is a given variable undefined?
11132  _.isUndefined = function(obj) {
11133    return obj === void 0;
11134  };
11135
11136  // Shortcut function for checking if an object has a given property directly
11137  // on itself (in other words, not on a prototype).
11138  _.has = function(obj, key) {
11139    return obj != null && hasOwnProperty.call(obj, key);
11140  };
11141
11142  // Utility Functions
11143  // -----------------
11144
11145  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
11146  // previous owner. Returns a reference to the Underscore object.
11147  _.noConflict = function() {
11148    root._ = previousUnderscore;
11149    return this;
11150  };
11151
11152  // Keep the identity function around for default iteratees.
11153  _.identity = function(value) {
11154    return value;
11155  };
11156
11157  // Predicate-generating functions. Often useful outside of Underscore.
11158  _.constant = function(value) {
11159    return function() {
11160      return value;
11161    };
11162  };
11163
11164  _.noop = function(){};
11165
11166  _.property = property;
11167
11168  // Generates a function for a given object that returns a given property.
11169  _.propertyOf = function(obj) {
11170    return obj == null ? function(){} : function(key) {
11171      return obj[key];
11172    };
11173  };
11174
11175  // Returns a predicate for checking whether an object has a given set of
11176  // `key:value` pairs.
11177  _.matcher = _.matches = function(attrs) {
11178    attrs = _.extendOwn({}, attrs);
11179    return function(obj) {
11180      return _.isMatch(obj, attrs);
11181    };
11182  };
11183
11184  // Run a function **n** times.
11185  _.times = function(n, iteratee, context) {
11186    var accum = Array(Math.max(0, n));
11187    iteratee = optimizeCb(iteratee, context, 1);
11188    for (var i = 0; i < n; i++) accum[i] = iteratee(i);
11189    return accum;
11190  };
11191
11192  // Return a random integer between min and max (inclusive).
11193  _.random = function(min, max) {
11194    if (max == null) {
11195      max = min;
11196      min = 0;
11197    }
11198    return min + Math.floor(Math.random() * (max - min + 1));
11199  };
11200
11201  // A (possibly faster) way to get the current timestamp as an integer.
11202  _.now = Date.now || function() {
11203    return new Date().getTime();
11204  };
11205
11206   // List of HTML entities for escaping.
11207  var escapeMap = {
11208    '&': '&amp;',
11209    '<': '&lt;',
11210    '>': '&gt;',
11211    '"': '&quot;',
11212    "'": '&#x27;',
11213    '`': '&#x60;'
11214  };
11215  var unescapeMap = _.invert(escapeMap);
11216
11217  // Functions for escaping and unescaping strings to/from HTML interpolation.
11218  var createEscaper = function(map) {
11219    var escaper = function(match) {
11220      return map[match];
11221    };
11222    // Regexes for identifying a key that needs to be escaped
11223    var source = '(?:' + _.keys(map).join('|') + ')';
11224    var testRegexp = RegExp(source);
11225    var replaceRegexp = RegExp(source, 'g');
11226    return function(string) {
11227      string = string == null ? '' : '' + string;
11228      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
11229    };
11230  };
11231  _.escape = createEscaper(escapeMap);
11232  _.unescape = createEscaper(unescapeMap);
11233
11234  // If the value of the named `property` is a function then invoke it with the
11235  // `object` as context; otherwise, return it.
11236  _.result = function(object, property, fallback) {
11237    var value = object == null ? void 0 : object[property];
11238    if (value === void 0) {
11239      value = fallback;
11240    }
11241    return _.isFunction(value) ? value.call(object) : value;
11242  };
11243
11244  // Generate a unique integer id (unique within the entire client session).
11245  // Useful for temporary DOM ids.
11246  var idCounter = 0;
11247  _.uniqueId = function(prefix) {
11248    var id = ++idCounter + '';
11249    return prefix ? prefix + id : id;
11250  };
11251
11252  // By default, Underscore uses ERB-style template delimiters, change the
11253  // following template settings to use alternative delimiters.
11254  _.templateSettings = {
11255    evaluate    : /<%([\s\S]+?)%>/g,
11256    interpolate : /<%=([\s\S]+?)%>/g,
11257    escape      : /<%-([\s\S]+?)%>/g
11258  };
11259
11260  // When customizing `templateSettings`, if you don't want to define an
11261  // interpolation, evaluation or escaping regex, we need one that is
11262  // guaranteed not to match.
11263  var noMatch = /(.)^/;
11264
11265  // Certain characters need to be escaped so that they can be put into a
11266  // string literal.
11267  var escapes = {
11268    "'":      "'",
11269    '\\':     '\\',
11270    '\r':     'r',
11271    '\n':     'n',
11272    '\u2028': 'u2028',
11273    '\u2029': 'u2029'
11274  };
11275
11276  var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
11277
11278  var escapeChar = function(match) {
11279    return '\\' + escapes[match];
11280  };
11281
11282  // JavaScript micro-templating, similar to John Resig's implementation.
11283  // Underscore templating handles arbitrary delimiters, preserves whitespace,
11284  // and correctly escapes quotes within interpolated code.
11285  // NB: `oldSettings` only exists for backwards compatibility.
11286  _.template = function(text, settings, oldSettings) {
11287    if (!settings && oldSettings) settings = oldSettings;
11288    settings = _.defaults({}, settings, _.templateSettings);
11289
11290    // Combine delimiters into one regular expression via alternation.
11291    var matcher = RegExp([
11292      (settings.escape || noMatch).source,
11293      (settings.interpolate || noMatch).source,
11294      (settings.evaluate || noMatch).source
11295    ].join('|') + '|$', 'g');
11296
11297    // Compile the template source, escaping string literals appropriately.
11298    var index = 0;
11299    var source = "__p+='";
11300    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
11301      source += text.slice(index, offset).replace(escaper, escapeChar);
11302      index = offset + match.length;
11303
11304      if (escape) {
11305        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
11306      } else if (interpolate) {
11307        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
11308      } else if (evaluate) {
11309        source += "';\n" + evaluate + "\n__p+='";
11310      }
11311
11312      // Adobe VMs need the match returned to produce the correct offest.
11313      return match;
11314    });
11315    source += "';\n";
11316
11317    // If a variable is not specified, place data values in local scope.
11318    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
11319
11320    source = "var __t,__p='',__j=Array.prototype.join," +
11321      "print=function(){__p+=__j.call(arguments,'');};\n" +
11322      source + 'return __p;\n';
11323
11324    try {
11325      var render = new Function(settings.variable || 'obj', '_', source);
11326    } catch (e) {
11327      e.source = source;
11328      throw e;
11329    }
11330
11331    var template = function(data) {
11332      return render.call(this, data, _);
11333    };
11334
11335    // Provide the compiled source as a convenience for precompilation.
11336    var argument = settings.variable || 'obj';
11337    template.source = 'function(' + argument + '){\n' + source + '}';
11338
11339    return template;
11340  };
11341
11342  // Add a "chain" function. Start chaining a wrapped Underscore object.
11343  _.chain = function(obj) {
11344    var instance = _(obj);
11345    instance._chain = true;
11346    return instance;
11347  };
11348
11349  // OOP
11350  // ---------------
11351  // If Underscore is called as a function, it returns a wrapped object that
11352  // can be used OO-style. This wrapper holds altered versions of all the
11353  // underscore functions. Wrapped objects may be chained.
11354
11355  // Helper function to continue chaining intermediate results.
11356  var result = function(instance, obj) {
11357    return instance._chain ? _(obj).chain() : obj;
11358  };
11359
11360  // Add your own custom functions to the Underscore object.
11361  _.mixin = function(obj) {
11362    _.each(_.functions(obj), function(name) {
11363      var func = _[name] = obj[name];
11364      _.prototype[name] = function() {
11365        var args = [this._wrapped];
11366        push.apply(args, arguments);
11367        return result(this, func.apply(_, args));
11368      };
11369    });
11370  };
11371
11372  // Add all of the Underscore functions to the wrapper object.
11373  _.mixin(_);
11374
11375  // Add all mutator Array functions to the wrapper.
11376  _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
11377    var method = ArrayProto[name];
11378    _.prototype[name] = function() {
11379      var obj = this._wrapped;
11380      method.apply(obj, arguments);
11381      if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
11382      return result(this, obj);
11383    };
11384  });
11385
11386  // Add all accessor Array functions to the wrapper.
11387  _.each(['concat', 'join', 'slice'], function(name) {
11388    var method = ArrayProto[name];
11389    _.prototype[name] = function() {
11390      return result(this, method.apply(this._wrapped, arguments));
11391    };
11392  });
11393
11394  // Extracts the result from a wrapped and chained object.
11395  _.prototype.value = function() {
11396    return this._wrapped;
11397  };
11398
11399  // Provide unwrapping proxy for some methods used in engine operations
11400  // such as arithmetic and JSON stringification.
11401  _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
11402
11403  _.prototype.toString = function() {
11404    return '' + this._wrapped;
11405  };
11406
11407  // AMD registration happens at the end for compatibility with AMD loaders
11408  // that may not enforce next-turn semantics on modules. Even though general
11409  // practice for AMD registration is to be anonymous, underscore registers
11410  // as a named module because, like jQuery, it is a base library that is
11411  // popular enough to be bundled in a third party lib, but not be part of
11412  // an AMD load request. Those cases could generate an error when an
11413  // anonymous define() is called outside of a loader request.
11414  if (typeof define === 'function' && define.amd) {
11415    define('underscore', [], function() {
11416      return _;
11417    });
11418  }
11419}.call(this));
11420
11421},{}],
1142154:[function(require,module,exports){
11422/*! VelocityJS.org (1.5.0). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */
11423
11424/*************************
11425 Velocity jQuery Shim
11426 *************************/
11427
vendor: 195,945 bytes, lines 11428-16057
11428/*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */
11429
11430/* This file contains the jQuery functions that Velocity relies on, thereby removing Velocity's dependency on a full copy of jQuery, and allowing it to work in any environment. */
11431/* These shimmed functions are only used if jQuery isn't present. If both this shim and jQuery are loaded, Velocity defaults to jQuery proper. */
11432/* Browser support: Using this shim instead of jQuery proper removes support for IE8. */
11433
11434(function(window) {
11435	"use strict";
11436	/***************
11437	 Setup
11438	 ***************/
11439
11440	/* If jQuery is already loaded, there's no point in loading this shim. */
11441	if (window.jQuery) {
11442		return;
11443	}
11444
11445	/* jQuery base. */
11446	var $ = function(selector, context) {
11447		return new $.fn.init(selector, context);
11448	};
11449
11450	/********************
11451	 Private Methods
11452	 ********************/
11453
11454	/* jQuery */
11455	$.isWindow = function(obj) {
11456		/* jshint eqeqeq: false */
11457		return obj && obj === obj.window;
11458	};
11459
11460	/* jQuery */
11461	$.type = function(obj) {
11462		if (!obj) {
11463			return obj + "";
11464		}
11465
11466		return typeof obj === "object" || typeof obj === "function" ?
11467				class2type[toString.call(obj)] || "object" :
11468				typeof obj;
11469	};
11470
11471	/* jQuery */
11472	$.isArray = Array.isArray || function(obj) {
11473		return $.type(obj) === "array";
11474	};
11475
11476	/* jQuery */
11477	function isArraylike(obj) {
11478		var length = obj.length,
11479				type = $.type(obj);
11480
11481		if (type === "function" || $.isWindow(obj)) {
11482			return false;
11483		}
11484
11485		if (obj.nodeType === 1 && length) {
11486			return true;
11487		}
11488
11489		return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj;
11490	}
11491
11492	/***************
11493	 $ Methods
11494	 ***************/
11495
11496	/* jQuery: Support removed for IE<9. */
11497	$.isPlainObject = function(obj) {
11498		var key;
11499
11500		if (!obj || $.type(obj) !== "object" || obj.nodeType || $.isWindow(obj)) {
11501			return false;
11502		}
11503
11504		try {
11505			if (obj.constructor &&
11506					!hasOwn.call(obj, "constructor") &&
11507					!hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
11508				return false;
11509			}
11510		} catch (e) {
11511			return false;
11512		}
11513
11514		for (key in obj) {
11515		}
11516
11517		return key === undefined || hasOwn.call(obj, key);
11518	};
11519
11520	/* jQuery */
11521	$.each = function(obj, callback, args) {
11522		var value,
11523				i = 0,
11524				length = obj.length,
11525				isArray = isArraylike(obj);
11526
11527		if (args) {
11528			if (isArray) {
11529				for (; i < length; i++) {
11530					value = callback.apply(obj[i], args);
11531
11532					if (value === false) {
11533						break;
11534					}
11535				}
11536			} else {
11537				for (i in obj) {
11538					if (!obj.hasOwnProperty(i)) {
11539						continue;
11540					}
11541					value = callback.apply(obj[i], args);
11542
11543					if (value === false) {
11544						break;
11545					}
11546				}
11547			}
11548
11549		} else {
11550			if (isArray) {
11551				for (; i < length; i++) {
11552					value = callback.call(obj[i], i, obj[i]);
11553
11554					if (value === false) {
11555						break;
11556					}
11557				}
11558			} else {
11559				for (i in obj) {
11560					if (!obj.hasOwnProperty(i)) {
11561						continue;
11562					}
11563					value = callback.call(obj[i], i, obj[i]);
11564
11565					if (value === false) {
11566						break;
11567					}
11568				}
11569			}
11570		}
11571
11572		return obj;
11573	};
11574
11575	/* Custom */
11576	$.data = function(node, key, value) {
11577		/* $.getData() */
11578		if (value === undefined) {
11579			var getId = node[$.expando],
11580					store = getId && cache[getId];
11581
11582			if (key === undefined) {
11583				return store;
11584			} else if (store) {
11585				if (key in store) {
11586					return store[key];
11587				}
11588			}
11589			/* $.setData() */
11590		} else if (key !== undefined) {
11591			var setId = node[$.expando] || (node[$.expando] = ++$.uuid);
11592
11593			cache[setId] = cache[setId] || {};
11594			cache[setId][key] = value;
11595
11596			return value;
11597		}
11598	};
11599
11600	/* Custom */
11601	$.removeData = function(node, keys) {
11602		var id = node[$.expando],
11603				store = id && cache[id];
11604
11605		if (store) {
11606			// Cleanup the entire store if no keys are provided.
11607			if (!keys) {
11608				delete cache[id];
11609			} else {
11610				$.each(keys, function(_, key) {
11611					delete store[key];
11612				});
11613			}
11614		}
11615	};
11616
11617	/* jQuery */
11618	$.extend = function() {
11619		var src, copyIsArray, copy, name, options, clone,
11620				target = arguments[0] || {},
11621				i = 1,
11622				length = arguments.length,
11623				deep = false;
11624
11625		if (typeof target === "boolean") {
11626			deep = target;
11627
11628			target = arguments[i] || {};
11629			i++;
11630		}
11631
11632		if (typeof target !== "object" && $.type(target) !== "function") {
11633			target = {};
11634		}
11635
11636		if (i === length) {
11637			target = this;
11638			i--;
11639		}
11640
11641		for (; i < length; i++) {
11642			if ((options = arguments[i])) {
11643				for (name in options) {
11644					if (!options.hasOwnProperty(name)) {
11645						continue;
11646					}
11647					src = target[name];
11648					copy = options[name];
11649
11650					if (target === copy) {
11651						continue;
11652					}
11653
11654					if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) {
11655						if (copyIsArray) {
11656							copyIsArray = false;
11657							clone = src && $.isArray(src) ? src : [];
11658
11659						} else {
11660							clone = src && $.isPlainObject(src) ? src : {};
11661						}
11662
11663						target[name] = $.extend(deep, clone, copy);
11664
11665					} else if (copy !== undefined) {
11666						target[name] = copy;
11667					}
11668				}
11669			}
11670		}
11671
11672		return target;
11673	};
11674
11675	/* jQuery 1.4.3 */
11676	$.queue = function(elem, type, data) {
11677		function $makeArray(arr, results) {
11678			var ret = results || [];
11679
11680			if (arr) {
11681				if (isArraylike(Object(arr))) {
11682					/* $.merge */
11683					(function(first, second) {
11684						var len = +second.length,
11685								j = 0,
11686								i = first.length;
11687
11688						while (j < len) {
11689							first[i++] = second[j++];
11690						}
11691
11692						if (len !== len) {
11693							while (second[j] !== undefined) {
11694								first[i++] = second[j++];
11695							}
11696						}
11697
11698						first.length = i;
11699
11700						return first;
11701					})(ret, typeof arr === "string" ? [arr] : arr);
11702				} else {
11703					[].push.call(ret, arr);
11704				}
11705			}
11706
11707			return ret;
11708		}
11709
11710		if (!elem) {
11711			return;
11712		}
11713
11714		type = (type || "fx") + "queue";
11715
11716		var q = $.data(elem, type);
11717
11718		if (!data) {
11719			return q || [];
11720		}
11721
11722		if (!q || $.isArray(data)) {
11723			q = $.data(elem, type, $makeArray(data));
11724		} else {
11725			q.push(data);
11726		}
11727
11728		return q;
11729	};
11730
11731	/* jQuery 1.4.3 */
11732	$.dequeue = function(elems, type) {
11733		/* Custom: Embed element iteration. */
11734		$.each(elems.nodeType ? [elems] : elems, function(i, elem) {
11735			type = type || "fx";
11736
11737			var queue = $.queue(elem, type),
11738					fn = queue.shift();
11739
11740			if (fn === "inprogress") {
11741				fn = queue.shift();
11742			}
11743
11744			if (fn) {
11745				if (type === "fx") {
11746					queue.unshift("inprogress");
11747				}
11748
11749				fn.call(elem, function() {
11750					$.dequeue(elem, type);
11751				});
11752			}
11753		});
11754	};
11755
11756	/******************
11757	 $.fn Methods
11758	 ******************/
11759
11760	/* jQuery */
11761	$.fn = $.prototype = {
11762		init: function(selector) {
11763			/* Just return the element wrapped inside an array; don't proceed with the actual jQuery node wrapping process. */
11764			if (selector.nodeType) {
11765				this[0] = selector;
11766
11767				return this;
11768			} else {
11769				throw new Error("Not a DOM node.");
11770			}
11771		},
11772		offset: function() {
11773			/* jQuery altered code: Dropped disconnected DOM node checking. */
11774			var box = this[0].getBoundingClientRect ? this[0].getBoundingClientRect() : {top: 0, left: 0};
11775
11776			return {
11777				top: box.top + (window.pageYOffset || document.scrollTop || 0) - (document.clientTop || 0),
11778				left: box.left + (window.pageXOffset || document.scrollLeft || 0) - (document.clientLeft || 0)
11779			};
11780		},
11781		position: function() {
11782			/* jQuery */
11783			function offsetParentFn(elem) {
11784				var offsetParent = elem.offsetParent;
11785
11786				while (offsetParent && (offsetParent.nodeName.toLowerCase() !== "html" && offsetParent.style && offsetParent.style.position.toLowerCase() === "static")) {
11787					offsetParent = offsetParent.offsetParent;
11788				}
11789
11790				return offsetParent || document;
11791			}
11792
11793			/* Zepto */
11794			var elem = this[0],
11795					offsetParent = offsetParentFn(elem),
11796					offset = this.offset(),
11797					parentOffset = /^(?:body|html)$/i.test(offsetParent.nodeName) ? {top: 0, left: 0} : $(offsetParent).offset();
11798
11799			offset.top -= parseFloat(elem.style.marginTop) || 0;
11800			offset.left -= parseFloat(elem.style.marginLeft) || 0;
11801
11802			if (offsetParent.style) {
11803				parentOffset.top += parseFloat(offsetParent.style.borderTopWidth) || 0;
11804				parentOffset.left += parseFloat(offsetParent.style.borderLeftWidth) || 0;
11805			}
11806
11807			return {
11808				top: offset.top - parentOffset.top,
11809				left: offset.left - parentOffset.left
11810			};
11811		}
11812	};
11813
11814	/**********************
11815	 Private Variables
11816	 **********************/
11817
11818	/* For $.data() */
11819	var cache = {};
11820	$.expando = "velocity" + (new Date().getTime());
11821	$.uuid = 0;
11822
11823	/* For $.queue() */
11824	var class2type = {},
11825			hasOwn = class2type.hasOwnProperty,
11826			toString = class2type.toString;
11827
11828	var types = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
11829	for (var i = 0; i < types.length; i++) {
11830		class2type["[object " + types[i] + "]"] = types[i].toLowerCase();
11831	}
11832
11833	/* Makes $(node) possible, without having to call init. */
11834	$.fn.init.prototype = $.fn;
11835
11836	/* Globalize Velocity onto the window, and assign its Utilities property. */
11837	window.Velocity = {Utilities: $};
11838})(window);
11839
11840/******************
11841 Velocity.js
11842 ******************/
11843
11844(function(factory) {
11845	"use strict";
11846	/* CommonJS module. */
11847	if (typeof module === "object" && typeof module.exports === "object") {
11848		module.exports = factory();
11849		/* AMD module. */
11850	} else if (typeof define === "function" && define.amd) {
11851		define(factory);
11852		/* Browser globals. */
11853	} else {
11854		factory();
11855	}
11856}(function() {
11857	"use strict";
11858	return function(global, window, document, undefined) {
11859
11860		/***************
11861		 Summary
11862		 ***************/
11863
11864		/*
11865		 - CSS: CSS stack that works independently from the rest of Velocity.
11866		 - animate(): Core animation method that iterates over the targeted elements and queues the incoming call onto each element individually.
11867		 - Pre-Queueing: Prepare the element for animation by instantiating its data cache and processing the call's options.
11868		 - Queueing: The logic that runs once the call has reached its point of execution in the element's $.queue() stack.
11869		 Most logic is placed here to avoid risking it becoming stale (if the element's properties have changed).
11870		 - Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container.
11871		 - tick(): The single requestAnimationFrame loop responsible for tweening all in-progress calls.
11872		 - completeCall(): Handles the cleanup process for each Velocity call.
11873		 */
11874
11875		/*********************
11876		 Helper Functions
11877		 *********************/
11878
11879		/* IE detection. Gist: https://gist.github.com/julianshapiro/9098609 */
11880		var IE = (function() {
11881			if (document.documentMode) {
11882				return document.documentMode;
11883			} else {
11884				for (var i = 7; i > 4; i--) {
11885					var div = document.createElement("div");
11886
11887					div.innerHTML = "<!--[if IE " + i + "]><span></span><![endif]-->";
11888
11889					if (div.getElementsByTagName("span").length) {
11890						div = null;
11891
11892						return i;
11893					}
11894				}
11895			}
11896
11897			return undefined;
11898		})();
11899
11900		/* rAF shim. Gist: https://gist.github.com/julianshapiro/9497513 */
11901		var rAFShim = (function() {
11902			var timeLast = 0;
11903
11904			return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
11905				var timeCurrent = (new Date()).getTime(),
11906						timeDelta;
11907
11908				/* Dynamically set delay on a per-tick basis to match 60fps. */
11909				/* Technique by Erik Moller. MIT license: https://gist.github.com/paulirish/1579671 */
11910				timeDelta = Math.max(0, 16 - (timeCurrent - timeLast));
11911				timeLast = timeCurrent + timeDelta;
11912
11913				return setTimeout(function() {
11914					callback(timeCurrent + timeDelta);
11915				}, timeDelta);
11916			};
11917		})();
11918
11919		var performance = (function() {
11920			var perf = window.performance || {};
11921
11922			if (typeof perf.now !== "function") {
11923				var nowOffset = perf.timing && perf.timing.navigationStart ? perf.timing.navigationStart : (new Date()).getTime();
11924
11925				perf.now = function() {
11926					return (new Date()).getTime() - nowOffset;
11927				};
11928			}
11929			return perf;
11930		})();
11931
11932		/* Array compacting. Copyright Lo-Dash. MIT License: https://github.com/lodash/lodash/blob/master/LICENSE.txt */
11933		function compactSparseArray(array) {
11934			var index = -1,
11935					length = array ? array.length : 0,
11936					result = [];
11937
11938			while (++index < length) {
11939				var value = array[index];
11940
11941				if (value) {
11942					result.push(value);
11943				}
11944			}
11945
11946			return result;
11947		}
11948
11949		/**
11950		 * Shim for "fixing" IE's lack of support (IE < 9) for applying slice
11951		 * on host objects like NamedNodeMap, NodeList, and HTMLCollection
11952		 * (technically, since host objects have been implementation-dependent,
11953		 * at least before ES2015, IE hasn't needed to work this way).
11954		 * Also works on strings, fixes IE < 9 to allow an explicit undefined
11955		 * for the 2nd argument (as in Firefox), and prevents errors when
11956		 * called on other DOM objects.
11957		 */
11958		var _slice = (function() {
11959			var slice = Array.prototype.slice;
11960
11961			try {
11962				// Can't be used with DOM elements in IE < 9
11963				slice.call(document.documentElement);
11964				return slice;
11965			} catch (e) { // Fails in IE < 9
11966
11967				// This will work for genuine arrays, array-like objects, 
11968				// NamedNodeMap (attributes, entities, notations),
11969				// NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
11970				// and will not fail on other DOM objects (as do DOM elements in IE < 9)
11971				return function(begin, end) {
11972					var len = this.length;
11973
11974					if (typeof begin !== "number") {
11975						begin = 0;
11976					}
11977					// IE < 9 gets unhappy with an undefined end argument
11978					if (typeof end !== "number") {
11979						end = len;
11980					}
11981					// For native Array objects, we use the native slice function
11982					if (this.slice) {
11983						return slice.call(this, begin, end);
11984					}
11985					// For array like object we handle it ourselves.
11986					var i,
11987							cloned = [],
11988							// Handle negative value for "begin"
11989							start = (begin >= 0) ? begin : Math.max(0, len + begin),
11990							// Handle negative value for "end"
11991							upTo = end < 0 ? len + end : Math.min(end, len),
11992							// Actual expected size of the slice
11993							size = upTo - start;
11994
11995					if (size > 0) {
11996						cloned = new Array(size);
11997						if (this.charAt) {
11998							for (i = 0; i < size; i++) {
11999								cloned[i] = this.charAt(start + i);
12000							}
12001						} else {
12002							for (i = 0; i < size; i++) {
12003								cloned[i] = this[start + i];
12004							}
12005						}
12006					}
12007					return cloned;
12008				};
12009			}
12010		})();
12011
12012		/* .indexOf doesn't exist in IE<9 */
12013		var _inArray = (function() {
12014			if (Array.prototype.includes) {
12015				return function(arr, val) {
12016					return arr.includes(val);
12017				};
12018			}
12019			if (Array.prototype.indexOf) {
12020				return function(arr, val) {
12021					return arr.indexOf(val) >= 0;
12022				};
12023			}
12024			return function(arr, val) {
12025				for (var i = 0; i < arr.length; i++) {
12026					if (arr[i] === val) {
12027						return true;
12028					}
12029				}
12030				return false;
12031			};
12032		});
12033
12034		function sanitizeElements(elements) {
12035			/* Unwrap jQuery/Zepto objects. */
12036			if (Type.isWrapped(elements)) {
12037				elements = _slice.call(elements);
12038				/* Wrap a single element in an array so that $.each() can iterate with the element instead of its node's children. */
12039			} else if (Type.isNode(elements)) {
12040				elements = [elements];
12041			}
12042
12043			return elements;
12044		}
12045
12046		var Type = {
12047			isNumber: function(variable) {
12048				return (typeof variable === "number");
12049			},
12050			isString: function(variable) {
12051				return (typeof variable === "string");
12052			},
12053			isArray: Array.isArray || function(variable) {
12054				return Object.prototype.toString.call(variable) === "[object Array]";
12055			},
12056			isFunction: function(variable) {
12057				return Object.prototype.toString.call(variable) === "[object Function]";
12058			},
12059			isNode: function(variable) {
12060				return variable && variable.nodeType;
12061			},
12062			/* Determine if variable is an array-like wrapped jQuery, Zepto or similar element, or even a NodeList etc. */
12063			/* NOTE: HTMLFormElements also have a length. */
12064			isWrapped: function(variable) {
12065				return variable
12066						&& variable !== window
12067						&& Type.isNumber(variable.length)
12068						&& !Type.isString(variable)
12069						&& !Type.isFunction(variable)
12070						&& !Type.isNode(variable)
12071						&& (variable.length === 0 || Type.isNode(variable[0]));
12072			},
12073			isSVG: function(variable) {
12074				return window.SVGElement && (variable instanceof window.SVGElement);
12075			},
12076			isEmptyObject: function(variable) {
12077				for (var name in variable) {
12078					if (variable.hasOwnProperty(name)) {
12079						return false;
12080					}
12081				}
12082
12083				return true;
12084			}
12085		};
12086
12087		/*****************
12088		 Dependencies
12089		 *****************/
12090
12091		var $,
12092				isJQuery = false;
12093
12094		if (global.fn && global.fn.jquery) {
12095			$ = global;
12096			isJQuery = true;
12097		} else {
12098			$ = window.Velocity.Utilities;
12099		}
12100
12101		if (IE <= 8 && !isJQuery) {
12102			throw new Error("Velocity: IE8 and below require jQuery to be loaded before Velocity.");
12103		} else if (IE <= 7) {
12104			/* Revert to jQuery's $.animate(), and lose Velocity's extra features. */
12105			jQuery.fn.velocity = jQuery.fn.animate;
12106
12107			/* Now that $.fn.velocity is aliased, abort this Velocity declaration. */
12108			return;
12109		}
12110
12111		/*****************
12112		 Constants
12113		 *****************/
12114
12115		var DURATION_DEFAULT = 400,
12116				EASING_DEFAULT = "swing";
12117
12118		/*************
12119		 State
12120		 *************/
12121
12122		var Velocity = {
12123			/* Container for page-wide Velocity state data. */
12124			State: {
12125				/* Detect mobile devices to determine if mobileHA should be turned on. */
12126				isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(window.navigator.userAgent),
12127				/* The mobileHA option's behavior changes on older Android devices (Gingerbread, versions 2.3.3-2.3.7). */
12128				isAndroid: /Android/i.test(window.navigator.userAgent),
12129				isGingerbread: /Android 2\.3\.[3-7]/i.test(window.navigator.userAgent),
12130				isChrome: window.chrome,
12131				isFirefox: /Firefox/i.test(window.navigator.userAgent),
12132				/* Create a cached element for re-use when checking for CSS property prefixes. */
12133				prefixElement: document.createElement("div"),
12134				/* Cache every prefix match to avoid repeating lookups. */
12135				prefixMatches: {},
12136				/* Cache the anchor used for animating window scrolling. */
12137				scrollAnchor: null,
12138				/* Cache the browser-specific property names associated with the scroll anchor. */
12139				scrollPropertyLeft: null,
12140				scrollPropertyTop: null,
12141				/* Keep track of whether our RAF tick is running. */
12142				isTicking: false,
12143				/* Container for every in-progress call to Velocity. */
12144				calls: [],
12145				delayedElements: {
12146					count: 0
12147				}
12148			},
12149			/* Velocity's custom CSS stack. Made global for unit testing. */
12150			CSS: {/* Defined below. */},
12151			/* A shim of the jQuery utility functions used by Velocity -- provided by Velocity's optional jQuery shim. */
12152			Utilities: $,
12153			/* Container for the user's custom animation redirects that are referenced by name in place of the properties map argument. */
12154			Redirects: {/* Manually registered by the user. */},
12155			Easings: {/* Defined below. */},
12156			/* Attempt to use ES6 Promises by default. Users can override this with a third-party promises library. */
12157			Promise: window.Promise,
12158			/* Velocity option defaults, which can be overriden by the user. */
12159			defaults: {
12160				queue: "",
12161				duration: DURATION_DEFAULT,
12162				easing: EASING_DEFAULT,
12163				begin: undefined,
12164				complete: undefined,
12165				progress: undefined,
12166				display: undefined,
12167				visibility: undefined,
12168				loop: false,
12169				delay: false,
12170				mobileHA: true,
12171				/* Advanced: Set to false to prevent property values from being cached between consecutive Velocity-initiated chain calls. */
12172				_cacheValues: true,
12173				/* Advanced: Set to false if the promise should always resolve on empty element lists. */
12174				promiseRejectEmpty: true
12175			},
12176			/* A design goal of Velocity is to cache data wherever possible in order to avoid DOM requerying. Accordingly, each element has a data cache. */
12177			init: function(element) {
12178				$.data(element, "velocity", {
12179					/* Store whether this is an SVG element, since its properties are retrieved and updated differently than standard HTML elements. */
12180					isSVG: Type.isSVG(element),
12181					/* Keep track of whether the element is currently being animated by Velocity.
12182					 This is used to ensure that property values are not transferred between non-consecutive (stale) calls. */
12183					isAnimating: false,
12184					/* A reference to the element's live computedStyle object. Learn more here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */
12185					computedStyle: null,
12186					/* Tween data is cached for each animation on the element so that data can be passed across calls --
12187					 in particular, end values are used as subsequent start values in consecutive Velocity calls. */
12188					tweensContainer: null,
12189					/* The full root property values of each CSS hook being animated on this element are cached so that:
12190					 1) Concurrently-animating hooks sharing the same root can have their root values' merged into one while tweening.
12191					 2) Post-hook-injection root values can be transferred over to consecutively chained Velocity calls as starting root values. */
12192					rootPropertyValueCache: {},
12193					/* A cache for transform updates, which must be manually flushed via CSS.flushTransformCache(). */
12194					transformCache: {}
12195				});
12196			},
12197			/* A parallel to jQuery's $.css(), used for getting/setting Velocity's hooked CSS properties. */
12198			hook: null, /* Defined below. */
12199			/* Velocity-wide animation time remapping for testing purposes. */
12200			mock: false,
12201			version: {major: 1, minor: 5, patch: 1},
12202			/* Set to 1 or 2 (most verbose) to output debug info to console. */
12203			debug: false,
12204			/* Use rAF high resolution timestamp when available */
12205			timestamp: true,
12206			/* Pause all animations */
12207			pauseAll: function(queueName) {
12208				var currentTime = (new Date()).getTime();
12209
12210				$.each(Velocity.State.calls, function(i, activeCall) {
12211
12212					if (activeCall) {
12213
12214						/* If we have a queueName and this call is not on that queue, skip */
12215						if (queueName !== undefined && ((activeCall[2].queue !== queueName) || (activeCall[2].queue === false))) {
12216							return true;
12217						}
12218
12219						/* Set call to paused */
12220						activeCall[5] = {
12221							resume: false
12222						};
12223					}
12224				});
12225
12226				/* Pause timers on any currently delayed calls */
12227				$.each(Velocity.State.delayedElements, function(k, element) {
12228					if (!element) {
12229						return;
12230					}
12231					pauseDelayOnElement(element, currentTime);
12232				});
12233			},
12234			/* Resume all animations */
12235			resumeAll: function(queueName) {
12236				var currentTime = (new Date()).getTime();
12237
12238				$.each(Velocity.State.calls, function(i, activeCall) {
12239
12240					if (activeCall) {
12241
12242						/* If we have a queueName and this call is not on that queue, skip */
12243						if (queueName !== undefined && ((activeCall[2].queue !== queueName) || (activeCall[2].queue === false))) {
12244							return true;
12245						}
12246
12247						/* Set call to resumed if it was paused */
12248						if (activeCall[5]) {
12249							activeCall[5].resume = true;
12250						}
12251					}
12252				});
12253				/* Resume timers on any currently delayed calls */
12254				$.each(Velocity.State.delayedElements, function(k, element) {
12255					if (!element) {
12256						return;
12257					}
12258					resumeDelayOnElement(element, currentTime);
12259				});
12260			}
12261		};
12262
12263		/* Retrieve the appropriate scroll anchor and property name for the browser: https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY */
12264		if (window.pageYOffset !== undefined) {
12265			Velocity.State.scrollAnchor = window;
12266			Velocity.State.scrollPropertyLeft = "pageXOffset";
12267			Velocity.State.scrollPropertyTop = "pageYOffset";
12268		} else {
12269			Velocity.State.scrollAnchor = document.documentElement || document.body.parentNode || document.body;
12270			Velocity.State.scrollPropertyLeft = "scrollLeft";
12271			Velocity.State.scrollPropertyTop = "scrollTop";
12272		}
12273
12274		/* Shorthand alias for jQuery's $.data() utility. */
12275		function Data(element) {
12276			/* Hardcode a reference to the plugin name. */
12277			var response = $.data(element, "velocity");
12278
12279			/* jQuery <=1.4.2 returns null instead of undefined when no match is found. We normalize this behavior. */
12280			return response === null ? undefined : response;
12281		}
12282
12283		/**************
12284		 Delay Timer
12285		 **************/
12286
12287		function pauseDelayOnElement(element, currentTime) {
12288			/* Check for any delay timers, and pause the set timeouts (while preserving time data)
12289			 to be resumed when the "resume" command is issued */
12290			var data = Data(element);
12291			if (data && data.delayTimer && !data.delayPaused) {
12292				data.delayRemaining = data.delay - currentTime + data.delayBegin;
12293				data.delayPaused = true;
12294				clearTimeout(data.delayTimer.setTimeout);
12295			}
12296		}
12297
12298		function resumeDelayOnElement(element, currentTime) {
12299			/* Check for any paused timers and resume */
12300			var data = Data(element);
12301			if (data && data.delayTimer && data.delayPaused) {
12302				/* If the element was mid-delay, re initiate the timeout with the remaining delay */
12303				data.delayPaused = false;
12304				data.delayTimer.setTimeout = setTimeout(data.delayTimer.next, data.delayRemaining);
12305			}
12306		}
12307
12308
12309
12310		/**************
12311		 Easing
12312		 **************/
12313
12314		/* Step easing generator. */
12315		function generateStep(steps) {
12316			return function(p) {
12317				return Math.round(p * steps) * (1 / steps);
12318			};
12319		}
12320
12321		/* Bezier curve function generator. Copyright Gaetan Renaudeau. MIT License: http://en.wikipedia.org/wiki/MIT_License */
12322		function generateBezier(mX1, mY1, mX2, mY2) {
12323			var NEWTON_ITERATIONS = 4,
12324					NEWTON_MIN_SLOPE = 0.001,
12325					SUBDIVISION_PRECISION = 0.0000001,
12326					SUBDIVISION_MAX_ITERATIONS = 10,
12327					kSplineTableSize = 11,
12328					kSampleStepSize = 1.0 / (kSplineTableSize - 1.0),
12329					float32ArraySupported = "Float32Array" in window;
12330
12331			/* Must contain four arguments. */
12332			if (arguments.length !== 4) {
12333				return false;
12334			}
12335
12336			/* Arguments must be numbers. */
12337			for (var i = 0; i < 4; ++i) {
12338				if (typeof arguments[i] !== "number" || isNaN(arguments[i]) || !isFinite(arguments[i])) {
12339					return false;
12340				}
12341			}
12342
12343			/* X values must be in the [0, 1] range. */
12344			mX1 = Math.min(mX1, 1);
12345			mX2 = Math.min(mX2, 1);
12346			mX1 = Math.max(mX1, 0);
12347			mX2 = Math.max(mX2, 0);
12348
12349			var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
12350
12351			function A(aA1, aA2) {
12352				return 1.0 - 3.0 * aA2 + 3.0 * aA1;
12353			}
12354			function B(aA1, aA2) {
12355				return 3.0 * aA2 - 6.0 * aA1;
12356			}
12357			function C(aA1) {
12358				return 3.0 * aA1;
12359			}
12360
12361			function calcBezier(aT, aA1, aA2) {
12362				return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
12363			}
12364
12365			function getSlope(aT, aA1, aA2) {
12366				return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
12367			}
12368
12369			function newtonRaphsonIterate(aX, aGuessT) {
12370				for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
12371					var currentSlope = getSlope(aGuessT, mX1, mX2);
12372
12373					if (currentSlope === 0.0) {
12374						return aGuessT;
12375					}
12376
12377					var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
12378					aGuessT -= currentX / currentSlope;
12379				}
12380
12381				return aGuessT;
12382			}
12383
12384			function calcSampleValues() {
12385				for (var i = 0; i < kSplineTableSize; ++i) {
12386					mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
12387				}
12388			}
12389
12390			function binarySubdivide(aX, aA, aB) {
12391				var currentX, currentT, i = 0;
12392
12393				do {
12394					currentT = aA + (aB - aA) / 2.0;
12395					currentX = calcBezier(currentT, mX1, mX2) - aX;
12396					if (currentX > 0.0) {
12397						aB = currentT;
12398					} else {
12399						aA = currentT;
12400					}
12401				} while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
12402
12403				return currentT;
12404			}
12405
12406			function getTForX(aX) {
12407				var intervalStart = 0.0,
12408						currentSample = 1,
12409						lastSample = kSplineTableSize - 1;
12410
12411				for (; currentSample !== lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
12412					intervalStart += kSampleStepSize;
12413				}
12414
12415				--currentSample;
12416
12417				var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample + 1] - mSampleValues[currentSample]),
12418						guessForT = intervalStart + dist * kSampleStepSize,
12419						initialSlope = getSlope(guessForT, mX1, mX2);
12420
12421				if (initialSlope >= NEWTON_MIN_SLOPE) {
12422					return newtonRaphsonIterate(aX, guessForT);
12423				} else if (initialSlope === 0.0) {
12424					return guessForT;
12425				} else {
12426					return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize);
12427				}
12428			}
12429
12430			var _precomputed = false;
12431
12432			function precompute() {
12433				_precomputed = true;
12434				if (mX1 !== mY1 || mX2 !== mY2) {
12435					calcSampleValues();
12436				}
12437			}
12438
12439			var f = function(aX) {
12440				if (!_precomputed) {
12441					precompute();
12442				}
12443				if (mX1 === mY1 && mX2 === mY2) {
12444					return aX;
12445				}
12446				if (aX === 0) {
12447					return 0;
12448				}
12449				if (aX === 1) {
12450					return 1;
12451				}
12452
12453				return calcBezier(getTForX(aX), mY1, mY2);
12454			};
12455
12456			f.getControlPoints = function() {
12457				return [{x: mX1, y: mY1}, {x: mX2, y: mY2}];
12458			};
12459
12460			var str = "generateBezier(" + [mX1, mY1, mX2, mY2] + ")";
12461			f.toString = function() {
12462				return str;
12463			};
12464
12465			return f;
12466		}
12467
12468		/* Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */
12469		/* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass
12470		 then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */
12471		var generateSpringRK4 = (function() {
12472			function springAccelerationForState(state) {
12473				return (-state.tension * state.x) - (state.friction * state.v);
12474			}
12475
12476			function springEvaluateStateWithDerivative(initialState, dt, derivative) {
12477				var state = {
12478					x: initialState.x + derivative.dx * dt,
12479					v: initialState.v + derivative.dv * dt,
12480					tension: initialState.tension,
12481					friction: initialState.friction
12482				};
12483
12484				return {dx: state.v, dv: springAccelerationForState(state)};
12485			}
12486
12487			function springIntegrateState(state, dt) {
12488				var a = {
12489					dx: state.v,
12490					dv: springAccelerationForState(state)
12491				},
12492						b = springEvaluateStateWithDerivative(state, dt * 0.5, a),
12493						c = springEvaluateStateWithDerivative(state, dt * 0.5, b),
12494						d = springEvaluateStateWithDerivative(state, dt, c),
12495						dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),
12496						dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);
12497
12498				state.x = state.x + dxdt * dt;
12499				state.v = state.v + dvdt * dt;
12500
12501				return state;
12502			}
12503
12504			return function springRK4Factory(tension, friction, duration) {
12505
12506				var initState = {
12507					x: -1,
12508					v: 0,
12509					tension: null,
12510					friction: null
12511				},
12512						path = [0],
12513						time_lapsed = 0,
12514						tolerance = 1 / 10000,
12515						DT = 16 / 1000,
12516						have_duration, dt, last_state;
12517
12518				tension = parseFloat(tension) || 500;
12519				friction = parseFloat(friction) || 20;
12520				duration = duration || null;
12521
12522				initState.tension = tension;
12523				initState.friction = friction;
12524
12525				have_duration = duration !== null;
12526
12527				/* Calculate the actual time it takes for this animation to complete with the provided conditions. */
12528				if (have_duration) {
12529					/* Run the simulation without a duration. */
12530					time_lapsed = springRK4Factory(tension, friction);
12531					/* Compute the adjusted time delta. */
12532					dt = time_lapsed / duration * DT;
12533				} else {
12534					dt = DT;
12535				}
12536
12537				while (true) {
12538					/* Next/step function .*/
12539					last_state = springIntegrateState(last_state || initState, dt);
12540					/* Store the position. */
12541					path.push(1 + last_state.x);
12542					time_lapsed += 16;
12543					/* If the change threshold is reached, break. */
12544					if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {
12545						break;
12546					}
12547				}
12548
12549				/* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the
12550				 computed path and returns a snapshot of the position according to a given percentComplete. */
12551				return !have_duration ? time_lapsed : function(percentComplete) {
12552					return path[ (percentComplete * (path.length - 1)) | 0 ];
12553				};
12554			};
12555		}());
12556
12557		/* jQuery easings. */
12558		Velocity.Easings = {
12559			linear: function(p) {
12560				return p;
12561			},
12562			swing: function(p) {
12563				return 0.5 - Math.cos(p * Math.PI) / 2;
12564			},
12565			/* Bonus "spring" easing, which is a less exaggerated version of easeInOutElastic. */
12566			spring: function(p) {
12567				return 1 - (Math.cos(p * 4.5 * Math.PI) * Math.exp(-p * 6));
12568			}
12569		};
12570
12571		/* CSS3 and Robert Penner easings. */
12572		$.each(
12573				[
12574					["ease", [0.25, 0.1, 0.25, 1.0]],
12575					["ease-in", [0.42, 0.0, 1.00, 1.0]],
12576					["ease-out", [0.00, 0.0, 0.58, 1.0]],
12577					["ease-in-out", [0.42, 0.0, 0.58, 1.0]],
12578					["easeInSine", [0.47, 0, 0.745, 0.715]],
12579					["easeOutSine", [0.39, 0.575, 0.565, 1]],
12580					["easeInOutSine", [0.445, 0.05, 0.55, 0.95]],
12581					["easeInQuad", [0.55, 0.085, 0.68, 0.53]],
12582					["easeOutQuad", [0.25, 0.46, 0.45, 0.94]],
12583					["easeInOutQuad", [0.455, 0.03, 0.515, 0.955]],
12584					["easeInCubic", [0.55, 0.055, 0.675, 0.19]],
12585					["easeOutCubic", [0.215, 0.61, 0.355, 1]],
12586					["easeInOutCubic", [0.645, 0.045, 0.355, 1]],
12587					["easeInQuart", [0.895, 0.03, 0.685, 0.22]],
12588					["easeOutQuart", [0.165, 0.84, 0.44, 1]],
12589					["easeInOutQuart", [0.77, 0, 0.175, 1]],
12590					["easeInQuint", [0.755, 0.05, 0.855, 0.06]],
12591					["easeOutQuint", [0.23, 1, 0.32, 1]],
12592					["easeInOutQuint", [0.86, 0, 0.07, 1]],
12593					["easeInExpo", [0.95, 0.05, 0.795, 0.035]],
12594					["easeOutExpo", [0.19, 1, 0.22, 1]],
12595					["easeInOutExpo", [1, 0, 0, 1]],
12596					["easeInCirc", [0.6, 0.04, 0.98, 0.335]],
12597					["easeOutCirc", [0.075, 0.82, 0.165, 1]],
12598					["easeInOutCirc", [0.785, 0.135, 0.15, 0.86]]
12599				], function(i, easingArray) {
12600			Velocity.Easings[easingArray[0]] = generateBezier.apply(null, easingArray[1]);
12601		});
12602
12603		/* Determine the appropriate easing type given an easing input. */
12604		function getEasing(value, duration) {
12605			var easing = value;
12606
12607			/* The easing option can either be a string that references a pre-registered easing,
12608			 or it can be a two-/four-item array of integers to be converted into a bezier/spring function. */
12609			if (Type.isString(value)) {
12610				/* Ensure that the easing has been assigned to jQuery's Velocity.Easings object. */
12611				if (!Velocity.Easings[value]) {
12612					easing = false;
12613				}
12614			} else if (Type.isArray(value) && value.length === 1) {
12615				easing = generateStep.apply(null, value);
12616			} else if (Type.isArray(value) && value.length === 2) {
12617				/* springRK4 must be passed the animation's duration. */
12618				/* Note: If the springRK4 array contains non-numbers, generateSpringRK4() returns an easing
12619				 function generated with default tension and friction values. */
12620				easing = generateSpringRK4.apply(null, value.concat([duration]));
12621			} else if (Type.isArray(value) && value.length === 4) {
12622				/* Note: If the bezier array contains non-numbers, generateBezier() returns false. */
12623				easing = generateBezier.apply(null, value);
12624			} else {
12625				easing = false;
12626			}
12627
12628			/* Revert to the Velocity-wide default easing type, or fall back to "swing" (which is also jQuery's default)
12629			 if the Velocity-wide default has been incorrectly modified. */
12630			if (easing === false) {
12631				if (Velocity.Easings[Velocity.defaults.easing]) {
12632					easing = Velocity.defaults.easing;
12633				} else {
12634					easing = EASING_DEFAULT;
12635				}
12636			}
12637
12638			return easing;
12639		}
12640
12641		/*****************
12642		 CSS Stack
12643		 *****************/
12644
12645		/* The CSS object is a highly condensed and performant CSS stack that fully replaces jQuery's.
12646		 It handles the validation, getting, and setting of both standard CSS properties and CSS property hooks. */
12647		/* Note: A "CSS" shorthand is aliased so that our code is easier to read. */
12648		var CSS = Velocity.CSS = {
12649			/*************
12650			 RegEx
12651			 *************/
12652
12653			RegEx: {
12654				isHex: /^#([A-f\d]{3}){1,2}$/i,
12655				/* Unwrap a property value's surrounding text, e.g. "rgba(4, 3, 2, 1)" ==> "4, 3, 2, 1" and "rect(4px 3px 2px 1px)" ==> "4px 3px 2px 1px". */
12656				valueUnwrap: /^[A-z]+\((.*)\)$/i,
12657				wrappedValueAlreadyExtracted: /[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/,
12658				/* Split a multi-value property into an array of subvalues, e.g. "rgba(4, 3, 2, 1) 4px 3px 2px 1px" ==> [ "rgba(4, 3, 2, 1)", "4px", "3px", "2px", "1px" ]. */
12659				valueSplit: /([A-z]+\(.+\))|(([A-z0-9#-.]+?)(?=\s|$))/ig
12660			},
12661			/************
12662			 Lists
12663			 ************/
12664
12665			Lists: {
12666				colors: ["fill", "stroke", "stopColor", "color", "backgroundColor", "borderColor", "borderTopColor", "borderRightColor", "borderBottomColor", "borderLeftColor", "outlineColor"],
12667				transformsBase: ["translateX", "translateY", "scale", "scaleX", "scaleY", "skewX", "skewY", "rotateZ"],
12668				transforms3D: ["transformPerspective", "translateZ", "scaleZ", "rotateX", "rotateY"],
12669				units: [
12670					"%", // relative
12671					"em", "ex", "ch", "rem", // font relative
12672					"vw", "vh", "vmin", "vmax", // viewport relative
12673					"cm", "mm", "Q", "in", "pc", "pt", "px", // absolute lengths
12674					"deg", "grad", "rad", "turn", // angles
12675					"s", "ms" // time
12676				],
12677				colorNames: {
12678					"aliceblue": "240,248,255",
12679					"antiquewhite": "250,235,215",
12680					"aquamarine": "127,255,212",
12681					"aqua": "0,255,255",
12682					"azure": "240,255,255",
12683					"beige": "245,245,220",
12684					"bisque": "255,228,196",
12685					"black": "0,0,0",
12686					"blanchedalmond": "255,235,205",
12687					"blueviolet": "138,43,226",
12688					"blue": "0,0,255",
12689					"brown": "165,42,42",
12690					"burlywood": "222,184,135",
12691					"cadetblue": "95,158,160",
12692					"chartreuse": "127,255,0",
12693					"chocolate": "210,105,30",
12694					"coral": "255,127,80",
12695					"cornflowerblue": "100,149,237",
12696					"cornsilk": "255,248,220",
12697					"crimson": "220,20,60",
12698					"cyan": "0,255,255",
12699					"darkblue": "0,0,139",
12700					"darkcyan": "0,139,139",
12701					"darkgoldenrod": "184,134,11",
12702					"darkgray": "169,169,169",
12703					"darkgrey": "169,169,169",
12704					"darkgreen": "0,100,0",
12705					"darkkhaki": "189,183,107",
12706					"darkmagenta": "139,0,139",
12707					"darkolivegreen": "85,107,47",
12708					"darkorange": "255,140,0",
12709					"darkorchid": "153,50,204",
12710					"darkred": "139,0,0",
12711					"darksalmon": "233,150,122",
12712					"darkseagreen": "143,188,143",
12713					"darkslateblue": "72,61,139",
12714					"darkslategray": "47,79,79",
12715					"darkturquoise": "0,206,209",
12716					"darkviolet": "148,0,211",
12717					"deeppink": "255,20,147",
12718					"deepskyblue": "0,191,255",
12719					"dimgray": "105,105,105",
12720					"dimgrey": "105,105,105",
12721					"dodgerblue": "30,144,255",
12722					"firebrick": "178,34,34",
12723					"floralwhite": "255,250,240",
12724					"forestgreen": "34,139,34",
12725					"fuchsia": "255,0,255",
12726					"gainsboro": "220,220,220",
12727					"ghostwhite": "248,248,255",
12728					"gold": "255,215,0",
12729					"goldenrod": "218,165,32",
12730					"gray": "128,128,128",
12731					"grey": "128,128,128",
12732					"greenyellow": "173,255,47",
12733					"green": "0,128,0",
12734					"honeydew": "240,255,240",
12735					"hotpink": "255,105,180",
12736					"indianred": "205,92,92",
12737					"indigo": "75,0,130",
12738					"ivory": "255,255,240",
12739					"khaki": "240,230,140",
12740					"lavenderblush": "255,240,245",
12741					"lavender": "230,230,250",
12742					"lawngreen": "124,252,0",
12743					"lemonchiffon": "255,250,205",
12744					"lightblue": "173,216,230",
12745					"lightcoral": "240,128,128",
12746					"lightcyan": "224,255,255",
12747					"lightgoldenrodyellow": "250,250,210",
12748					"lightgray": "211,211,211",
12749					"lightgrey": "211,211,211",
12750					"lightgreen": "144,238,144",
12751					"lightpink": "255,182,193",
12752					"lightsalmon": "255,160,122",
12753					"lightseagreen": "32,178,170",
12754					"lightskyblue": "135,206,250",
12755					"lightslategray": "119,136,153",
12756					"lightsteelblue": "176,196,222",
12757					"lightyellow": "255,255,224",
12758					"limegreen": "50,205,50",
12759					"lime": "0,255,0",
12760					"linen": "250,240,230",
12761					"magenta": "255,0,255",
12762					"maroon": "128,0,0",
12763					"mediumaquamarine": "102,205,170",
12764					"mediumblue": "0,0,205",
12765					"mediumorchid": "186,85,211",
12766					"mediumpurple": "147,112,219",
12767					"mediumseagreen": "60,179,113",
12768					"mediumslateblue": "123,104,238",
12769					"mediumspringgreen": "0,250,154",
12770					"mediumturquoise": "72,209,204",
12771					"mediumvioletred": "199,21,133",
12772					"midnightblue": "25,25,112",
12773					"mintcream": "245,255,250",
12774					"mistyrose": "255,228,225",
12775					"moccasin": "255,228,181",
12776					"navajowhite": "255,222,173",
12777					"navy": "0,0,128",
12778					"oldlace": "253,245,230",
12779					"olivedrab": "107,142,35",
12780					"olive": "128,128,0",
12781					"orangered": "255,69,0",
12782					"orange": "255,165,0",
12783					"orchid": "218,112,214",
12784					"palegoldenrod": "238,232,170",
12785					"palegreen": "152,251,152",
12786					"paleturquoise": "175,238,238",
12787					"palevioletred": "219,112,147",
12788					"papayawhip": "255,239,213",
12789					"peachpuff": "255,218,185",
12790					"peru": "205,133,63",
12791					"pink": "255,192,203",
12792					"plum": "221,160,221",
12793					"powderblue": "176,224,230",
12794					"purple": "128,0,128",
12795					"red": "255,0,0",
12796					"rosybrown": "188,143,143",
12797					"royalblue": "65,105,225",
12798					"saddlebrown": "139,69,19",
12799					"salmon": "250,128,114",
12800					"sandybrown": "244,164,96",
12801					"seagreen": "46,139,87",
12802					"seashell": "255,245,238",
12803					"sienna": "160,82,45",
12804					"silver": "192,192,192",
12805					"skyblue": "135,206,235",
12806					"slateblue": "106,90,205",
12807					"slategray": "112,128,144",
12808					"snow": "255,250,250",
12809					"springgreen": "0,255,127",
12810					"steelblue": "70,130,180",
12811					"tan": "210,180,140",
12812					"teal": "0,128,128",
12813					"thistle": "216,191,216",
12814					"tomato": "255,99,71",
12815					"turquoise": "64,224,208",
12816					"violet": "238,130,238",
12817					"wheat": "245,222,179",
12818					"whitesmoke": "245,245,245",
12819					"white": "255,255,255",
12820					"yellowgreen": "154,205,50",
12821					"yellow": "255,255,0"
12822				}
12823			},
12824			/************
12825			 Hooks
12826			 ************/
12827
12828			/* Hooks allow a subproperty (e.g. "boxShadowBlur") of a compound-value CSS property
12829			 (e.g. "boxShadow: X Y Blur Spread Color") to be animated as if it were a discrete property. */
12830			/* Note: Beyond enabling fine-grained property animation, hooking is necessary since Velocity only
12831			 tweens properties with single numeric values; unlike CSS transitions, Velocity does not interpolate compound-values. */
12832			Hooks: {
12833				/********************
12834				 Registration
12835				 ********************/
12836
12837				/* Templates are a concise way of indicating which subproperties must be individually registered for each compound-value CSS property. */
12838				/* Each template consists of the compound-value's base name, its constituent subproperty names, and those subproperties' default values. */
12839				templates: {
12840					"textShadow": ["Color X Y Blur", "black 0px 0px 0px"],
12841					"boxShadow": ["Color X Y Blur Spread", "black 0px 0px 0px 0px"],
12842					"clip": ["Top Right Bottom Left", "0px 0px 0px 0px"],
12843					"backgroundPosition": ["X Y", "0% 0%"],
12844					"transformOrigin": ["X Y Z", "50% 50% 0px"],
12845					"perspectiveOrigin": ["X Y", "50% 50%"]
12846				},
12847				/* A "registered" hook is one that has been converted from its template form into a live,
12848				 tweenable property. It contains data to associate it with its root property. */
12849				registered: {
12850					/* Note: A registered hook looks like this ==> textShadowBlur: [ "textShadow", 3 ],
12851					 which consists of the subproperty's name, the associated root property's name,
12852					 and the subproperty's position in the root's value. */
12853				},
12854				/* Convert the templates into individual hooks then append them to the registered object above. */
12855				register: function() {
12856					/* Color hooks registration: Colors are defaulted to white -- as opposed to black -- since colors that are
12857					 currently set to "transparent" default to their respective template below when color-animated,
12858					 and white is typically a closer match to transparent than black is. An exception is made for text ("color"),
12859					 which is almost always set closer to black than white. */
12860					for (var i = 0; i < CSS.Lists.colors.length; i++) {
12861						var rgbComponents = (CSS.Lists.colors[i] === "color") ? "0 0 0 1" : "255 255 255 1";
12862						CSS.Hooks.templates[CSS.Lists.colors[i]] = ["Red Green Blue Alpha", rgbComponents];
12863					}
12864
12865					var rootProperty,
12866							hookTemplate,
12867							hookNames;
12868
12869					/* In IE, color values inside compound-value properties are positioned at the end the value instead of at the beginning.
12870					 Thus, we re-arrange the templates accordingly. */
12871					if (IE) {
12872						for (rootProperty in CSS.Hooks.templates) {
12873							if (!CSS.Hooks.templates.hasOwnProperty(rootProperty)) {
12874								continue;
12875							}
12876							hookTemplate = CSS.Hooks.templates[rootProperty];
12877							hookNames = hookTemplate[0].split(" ");
12878
12879							var defaultValues = hookTemplate[1].match(CSS.RegEx.valueSplit);
12880
12881							if (hookNames[0] === "Color") {
12882								/* Reposition both the hook's name and its default value to the end of their respective strings. */
12883								hookNames.push(hookNames.shift());
12884								defaultValues.push(defaultValues.shift());
12885
12886								/* Replace the existing template for the hook's root property. */
12887								CSS.Hooks.templates[rootProperty] = [hookNames.join(" "), defaultValues.join(" ")];
12888							}
12889						}
12890					}
12891
12892					/* Hook registration. */
12893					for (rootProperty in CSS.Hooks.templates) {
12894						if (!CSS.Hooks.templates.hasOwnProperty(rootProperty)) {
12895							continue;
12896						}
12897						hookTemplate = CSS.Hooks.templates[rootProperty];
12898						hookNames = hookTemplate[0].split(" ");
12899
12900						for (var j in hookNames) {
12901							if (!hookNames.hasOwnProperty(j)) {
12902								continue;
12903							}
12904							var fullHookName = rootProperty + hookNames[j],
12905									hookPosition = j;
12906
12907							/* For each hook, register its full name (e.g. textShadowBlur) with its root property (e.g. textShadow)
12908							 and the hook's position in its template's default value string. */
12909							CSS.Hooks.registered[fullHookName] = [rootProperty, hookPosition];
12910						}
12911					}
12912				},
12913				/*****************************
12914				 Injection and Extraction
12915				 *****************************/
12916
12917				/* Look up the root property associated with the hook (e.g. return "textShadow" for "textShadowBlur"). */
12918				/* Since a hook cannot be set directly (the browser won't recognize it), style updating for hooks is routed through the hook's root property. */
12919				getRoot: function(property) {
12920					var hookData = CSS.Hooks.registered[property];
12921
12922					if (hookData) {
12923						return hookData[0];
12924					} else {
12925						/* If there was no hook match, return the property name untouched. */
12926						return property;
12927					}
12928				},
12929				getUnit: function(str, start) {
12930					var unit = (str.substr(start || 0, 5).match(/^[a-z%]+/) || [])[0] || "";
12931
12932					if (unit && _inArray(CSS.Lists.units, unit)) {
12933						return unit;
12934					}
12935					return "";
12936				},
12937				fixColors: function(str) {
12938					return str.replace(/(rgba?\(\s*)?(\b[a-z]+\b)/g, function($0, $1, $2) {
12939						if (CSS.Lists.colorNames.hasOwnProperty($2)) {
12940							return ($1 ? $1 : "rgba(") + CSS.Lists.colorNames[$2] + ($1 ? "" : ",1)");
12941						}
12942						return $1 + $2;
12943					});
12944				},
12945				/* Convert any rootPropertyValue, null or otherwise, into a space-delimited list of hook values so that
12946				 the targeted hook can be injected or extracted at its standard position. */
12947				cleanRootPropertyValue: function(rootProperty, rootPropertyValue) {
12948					/* If the rootPropertyValue is wrapped with "rgb()", "clip()", etc., remove the wrapping to normalize the value before manipulation. */
12949					if (CSS.RegEx.valueUnwrap.test(rootPropertyValue)) {
12950						rootPropertyValue = rootPropertyValue.match(CSS.RegEx.valueUnwrap)[1];
12951					}
12952
12953					/* If rootPropertyValue is a CSS null-value (from which there's inherently no hook value to extract),
12954					 default to the root's default value as defined in CSS.Hooks.templates. */
12955					/* Note: CSS null-values include "none", "auto", and "transparent". They must be converted into their
12956					 zero-values (e.g. textShadow: "none" ==> textShadow: "0px 0px 0px black") for hook manipulation to proceed. */
12957					if (CSS.Values.isCSSNullValue(rootPropertyValue)) {
12958						rootPropertyValue = CSS.Hooks.templates[rootProperty][1];
12959					}
12960
12961					return rootPropertyValue;
12962				},
12963				/* Extracted the hook's value from its root property's value. This is used to get the starting value of an animating hook. */
12964				extractValue: function(fullHookName, rootPropertyValue) {
12965					var hookData = CSS.Hooks.registered[fullHookName];
12966
12967					if (hookData) {
12968						var hookRoot = hookData[0],
12969								hookPosition = hookData[1];
12970
12971						rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue);
12972
12973						/* Split rootPropertyValue into its constituent hook values then grab the desired hook at its standard position. */
12974						return rootPropertyValue.toString().match(CSS.RegEx.valueSplit)[hookPosition];
12975					} else {
12976						/* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */
12977						return rootPropertyValue;
12978					}
12979				},
12980				/* Inject the hook's value into its root property's value. This is used to piece back together the root property
12981				 once Velocity has updated one of its individually hooked values through tweening. */
12982				injectValue: function(fullHookName, hookValue, rootPropertyValue) {
12983					var hookData = CSS.Hooks.registered[fullHookName];
12984
12985					if (hookData) {
12986						var hookRoot = hookData[0],
12987								hookPosition = hookData[1],
12988								rootPropertyValueParts,
12989								rootPropertyValueUpdated;
12990
12991						rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue);
12992
12993						/* Split rootPropertyValue into its individual hook values, replace the targeted value with hookValue,
12994						 then reconstruct the rootPropertyValue string. */
12995						rootPropertyValueParts = rootPropertyValue.toString().match(CSS.RegEx.valueSplit);
12996						rootPropertyValueParts[hookPosition] = hookValue;
12997						rootPropertyValueUpdated = rootPropertyValueParts.join(" ");
12998
12999						return rootPropertyValueUpdated;
13000					} else {
13001						/* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */
13002						return rootPropertyValue;
13003					}
13004				}
13005			},
13006			/*******************
13007			 Normalizations
13008			 *******************/
13009
13010			/* Normalizations standardize CSS property manipulation by pollyfilling browser-specific implementations (e.g. opacity)
13011			 and reformatting special properties (e.g. clip, rgba) to look like standard ones. */
13012			Normalizations: {
13013				/* Normalizations are passed a normalization target (either the property's name, its extracted value, or its injected value),
13014				 the targeted element (which may need to be queried), and the targeted property value. */
13015				registered: {
13016					clip: function(type, element, propertyValue) {
13017						switch (type) {
13018							case "name":
13019								return "clip";
13020								/* Clip needs to be unwrapped and stripped of its commas during extraction. */
13021							case "extract":
13022								var extracted;
13023
13024								/* If Velocity also extracted this value, skip extraction. */
13025								if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) {
13026									extracted = propertyValue;
13027								} else {
13028									/* Remove the "rect()" wrapper. */
13029									extracted = propertyValue.toString().match(CSS.RegEx.valueUnwrap);
13030
13031									/* Strip off commas. */
13032									extracted = extracted ? extracted[1].replace(/,(\s+)?/g, " ") : propertyValue;
13033								}
13034
13035								return extracted;
13036								/* Clip needs to be re-wrapped during injection. */
13037							case "inject":
13038								return "rect(" + propertyValue + ")";
13039						}
13040					},
13041					blur: function(type, element, propertyValue) {
13042						switch (type) {
13043							case "name":
13044								return Velocity.State.isFirefox ? "filter" : "-webkit-filter";
13045							case "extract":
13046								var extracted = parseFloat(propertyValue);
13047
13048								/* If extracted is NaN, meaning the value isn't already extracted. */
13049								if (!(extracted || extracted === 0)) {
13050									var blurComponent = propertyValue.toString().match(/blur\(([0-9]+[A-z]+)\)/i);
13051
13052									/* If the filter string had a blur component, return just the blur value and unit type. */
13053									if (blurComponent) {
13054										extracted = blurComponent[1];
13055										/* If the component doesn't exist, default blur to 0. */
13056									} else {
13057										extracted = 0;
13058									}
13059								}
13060
13061								return extracted;
13062								/* Blur needs to be re-wrapped during injection. */
13063							case "inject":
13064								/* For the blur effect to be fully de-applied, it needs to be set to "none" instead of 0. */
13065								if (!parseFloat(propertyValue)) {
13066									return "none";
13067								} else {
13068									return "blur(" + propertyValue + ")";
13069								}
13070						}
13071					},
13072					/* <=IE8 do not support the standard opacity property. They use filter:alpha(opacity=INT) instead. */
13073					opacity: function(type, element, propertyValue) {
13074						if (IE <= 8) {
13075							switch (type) {
13076								case "name":
13077									return "filter";
13078								case "extract":
13079									/* <=IE8 return a "filter" value of "alpha(opacity=\d{1,3})".
13080									 Extract the value and convert it to a decimal value to match the standard CSS opacity property's formatting. */
13081									var extracted = propertyValue.toString().match(/alpha\(opacity=(.*)\)/i);
13082
13083									if (extracted) {
13084										/* Convert to decimal value. */
13085										propertyValue = extracted[1] / 100;
13086									} else {
13087										/* When extracting opacity, default to 1 since a null value means opacity hasn't been set. */
13088										propertyValue = 1;
13089									}
13090
13091									return propertyValue;
13092								case "inject":
13093									/* Opacified elements are required to have their zoom property set to a non-zero value. */
13094									element.style.zoom = 1;
13095
13096									/* Setting the filter property on elements with certain font property combinations can result in a
13097									 highly unappealing ultra-bolding effect. There's no way to remedy this throughout a tween, but dropping the
13098									 value altogether (when opacity hits 1) at leasts ensures that the glitch is gone post-tweening. */
13099									if (parseFloat(propertyValue) >= 1) {
13100										return "";
13101									} else {
13102										/* As per the filter property's spec, convert the decimal value to a whole number and wrap the value. */
13103										return "alpha(opacity=" + parseInt(parseFloat(propertyValue) * 100, 10) + ")";
13104									}
13105							}
13106							/* With all other browsers, normalization is not required; return the same values that were passed in. */
13107						} else {
13108							switch (type) {
13109								case "name":
13110									return "opacity";
13111								case "extract":
13112									return propertyValue;
13113								case "inject":
13114									return propertyValue;
13115							}
13116						}
13117					}
13118				},
13119				/*****************************
13120				 Batched Registrations
13121				 *****************************/
13122
13123				/* Note: Batched normalizations extend the CSS.Normalizations.registered object. */
13124				register: function() {
13125
13126					/*****************
13127					 Transforms
13128					 *****************/
13129
13130					/* Transforms are the subproperties contained by the CSS "transform" property. Transforms must undergo normalization
13131					 so that they can be referenced in a properties map by their individual names. */
13132					/* Note: When transforms are "set", they are actually assigned to a per-element transformCache. When all transform
13133					 setting is complete complete, CSS.flushTransformCache() must be manually called to flush the values to the DOM.
13134					 Transform setting is batched in this way to improve performance: the transform style only needs to be updated
13135					 once when multiple transform subproperties are being animated simultaneously. */
13136					/* Note: IE9 and Android Gingerbread have support for 2D -- but not 3D -- transforms. Since animating unsupported
13137					 transform properties results in the browser ignoring the *entire* transform string, we prevent these 3D values
13138					 from being normalized for these browsers so that tweening skips these properties altogether
13139					 (since it will ignore them as being unsupported by the browser.) */
13140					if ((!IE || IE > 9) && !Velocity.State.isGingerbread) {
13141						/* Note: Since the standalone CSS "perspective" property and the CSS transform "perspective" subproperty
13142						 share the same name, the latter is given a unique token within Velocity: "transformPerspective". */
13143						CSS.Lists.transformsBase = CSS.Lists.transformsBase.concat(CSS.Lists.transforms3D);
13144					}
13145
13146					for (var i = 0; i < CSS.Lists.transformsBase.length; i++) {
13147						/* Wrap the dynamically generated normalization function in a new scope so that transformName's value is
13148						 paired with its respective function. (Otherwise, all functions would take the final for loop's transformName.) */
13149						(function() {
13150							var transformName = CSS.Lists.transformsBase[i];
13151
13152							CSS.Normalizations.registered[transformName] = function(type, element, propertyValue) {
13153								switch (type) {
13154									/* The normalized property name is the parent "transform" property -- the property that is actually set in CSS. */
13155									case "name":
13156										return "transform";
13157										/* Transform values are cached onto a per-element transformCache object. */
13158									case "extract":
13159										/* If this transform has yet to be assigned a value, return its null value. */
13160										if (Data(element) === undefined || Data(element).transformCache[transformName] === undefined) {
13161											/* Scale CSS.Lists.transformsBase default to 1 whereas all other transform properties default to 0. */
13162											return /^scale/i.test(transformName) ? 1 : 0;
13163											/* When transform values are set, they are wrapped in parentheses as per the CSS spec.
13164											 Thus, when extracting their values (for tween calculations), we strip off the parentheses. */
13165										}
13166										return Data(element).transformCache[transformName].replace(/[()]/g, "");
13167									case "inject":
13168										var invalid = false;
13169
13170										/* If an individual transform property contains an unsupported unit type, the browser ignores the *entire* transform property.
13171										 Thus, protect users from themselves by skipping setting for transform values supplied with invalid unit types. */
13172										/* Switch on the base transform type; ignore the axis by removing the last letter from the transform's name. */
13173										switch (transformName.substr(0, transformName.length - 1)) {
13174											/* Whitelist unit types for each transform. */
13175											case "translate":
13176												invalid = !/(%|px|em|rem|vw|vh|\d)$/i.test(propertyValue);
13177												break;
13178												/* Since an axis-free "scale" property is supported as well, a little hack is used here to detect it by chopping off its last letter. */
13179											case "scal":
13180											case "scale":
13181												/* Chrome on Android has a bug in which scaled elements blur if their initial scale
13182												 value is below 1 (which can happen with forcefeeding). Thus, we detect a yet-unset scale property
13183												 and ensure that its first value is always 1. More info: http://stackoverflow.com/questions/10417890/css3-animations-with-transform-causes-blurred-elements-on-webkit/10417962#10417962 */
13184												if (Velocity.State.isAndroid && Data(element).transformCache[transformName] === undefined && propertyValue < 1) {
13185													propertyValue = 1;
13186												}
13187
13188												invalid = !/(\d)$/i.test(propertyValue);
13189												break;
13190											case "skew":
13191												invalid = !/(deg|\d)$/i.test(propertyValue);
13192												break;
13193											case "rotate":
13194												invalid = !/(deg|\d)$/i.test(propertyValue);
13195												break;
13196										}
13197
13198										if (!invalid) {
13199											/* As per the CSS spec, wrap the value in parentheses. */
13200											Data(element).transformCache[transformName] = "(" + propertyValue + ")";
13201										}
13202
13203										/* Although the value is set on the transformCache object, return the newly-updated value for the calling code to process as normal. */
13204										return Data(element).transformCache[transformName];
13205								}
13206							};
13207						})();
13208					}
13209
13210					/*************
13211					 Colors
13212					 *************/
13213
13214					/* Since Velocity only animates a single numeric value per property, color animation is achieved by hooking the individual RGBA components of CSS color properties.
13215					 Accordingly, color values must be normalized (e.g. "#ff0000", "red", and "rgb(255, 0, 0)" ==> "255 0 0 1") so that their components can be injected/extracted by CSS.Hooks logic. */
13216					for (var j = 0; j < CSS.Lists.colors.length; j++) {
13217						/* Wrap the dynamically generated normalization function in a new scope so that colorName's value is paired with its respective function.
13218						 (Otherwise, all functions would take the final for loop's colorName.) */
13219						(function() {
13220							var colorName = CSS.Lists.colors[j];
13221
13222							/* Note: In IE<=8, which support rgb but not rgba, color properties are reverted to rgb by stripping off the alpha component. */
13223							CSS.Normalizations.registered[colorName] = function(type, element, propertyValue) {
13224								switch (type) {
13225									case "name":
13226										return colorName;
13227										/* Convert all color values into the rgb format. (Old IE can return hex values and color names instead of rgb/rgba.) */
13228									case "extract":
13229										var extracted;
13230
13231										/* If the color is already in its hookable form (e.g. "255 255 255 1") due to having been previously extracted, skip extraction. */
13232										if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) {
13233											extracted = propertyValue;
13234										} else {
13235											var converted,
13236													colorNames = {
13237														black: "rgb(0, 0, 0)",
13238														blue: "rgb(0, 0, 255)",
13239														gray: "rgb(128, 128, 128)",
13240														green: "rgb(0, 128, 0)",
13241														red: "rgb(255, 0, 0)",
13242														white: "rgb(255, 255, 255)"
13243													};
13244
13245											/* Convert color names to rgb. */
13246											if (/^[A-z]+$/i.test(propertyValue)) {
13247												if (colorNames[propertyValue] !== undefined) {
13248													converted = colorNames[propertyValue];
13249												} else {
13250													/* If an unmatched color name is provided, default to black. */
13251													converted = colorNames.black;
13252												}
13253												/* Convert hex values to rgb. */
13254											} else if (CSS.RegEx.isHex.test(propertyValue)) {
13255												converted = "rgb(" + CSS.Values.hexToRgb(propertyValue).join(" ") + ")";
13256												/* If the provided color doesn't match any of the accepted color formats, default to black. */
13257											} else if (!(/^rgba?\(/i.test(propertyValue))) {
13258												converted = colorNames.black;
13259											}
13260
13261											/* Remove the surrounding "rgb/rgba()" string then replace commas with spaces and strip
13262											 repeated spaces (in case the value included spaces to begin with). */
13263											extracted = (converted || propertyValue).toString().match(CSS.RegEx.valueUnwrap)[1].replace(/,(\s+)?/g, " ");
13264										}
13265
13266										/* So long as this isn't <=IE8, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
13267										if ((!IE || IE > 8) && extracted.split(" ").length === 3) {
13268											extracted += " 1";
13269										}
13270
13271										return extracted;
13272									case "inject":
13273										/* If we have a pattern then it might already have the right values */
13274										if (/^rgb/.test(propertyValue)) {
13275											return propertyValue;
13276										}
13277
13278										/* If this is IE<=8 and an alpha component exists, strip it off. */
13279										if (IE <= 8) {
13280											if (propertyValue.split(" ").length === 4) {
13281												propertyValue = propertyValue.split(/\s+/).slice(0, 3).join(" ");
13282											}
13283											/* Otherwise, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
13284										} else if (propertyValue.split(" ").length === 3) {
13285											propertyValue += " 1";
13286										}
13287
13288										/* Re-insert the browser-appropriate wrapper("rgb/rgba()"), insert commas, and strip off decimal units
13289										 on all values but the fourth (R, G, and B only accept whole numbers). */
13290										return (IE <= 8 ? "rgb" : "rgba") + "(" + propertyValue.replace(/\s+/g, ",").replace(/\.(\d)+(?=,)/g, "") + ")";
13291								}
13292							};
13293						})();
13294					}
13295
13296					/**************
13297					 Dimensions
13298					 **************/
13299					function augmentDimension(name, element, wantInner) {
13300						var isBorderBox = CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() === "border-box";
13301
13302						if (isBorderBox === (wantInner || false)) {
13303							/* in box-sizing mode, the CSS width / height accessors already give the outerWidth / outerHeight. */
13304							var i,
13305									value,
13306									augment = 0,
13307									sides = name === "width" ? ["Left", "Right"] : ["Top", "Bottom"],
13308									fields = ["padding" + sides[0], "padding" + sides[1], "border" + sides[0] + "Width", "border" + sides[1] + "Width"];
13309
13310							for (i = 0; i < fields.length; i++) {
13311								value = parseFloat(CSS.getPropertyValue(element, fields[i]));
13312								if (!isNaN(value)) {
13313									augment += value;
13314								}
13315							}
13316							return wantInner ? -augment : augment;
13317						}
13318						return 0;
13319					}
13320					function getDimension(name, wantInner) {
13321						return function(type, element, propertyValue) {
13322							switch (type) {
13323								case "name":
13324									return name;
13325								case "extract":
13326									return parseFloat(propertyValue) + augmentDimension(name, element, wantInner);
13327								case "inject":
13328									return (parseFloat(propertyValue) - augmentDimension(name, element, wantInner)) + "px";
13329							}
13330						};
13331					}
13332					CSS.Normalizations.registered.innerWidth = getDimension("width", true);
13333					CSS.Normalizations.registered.innerHeight = getDimension("height", true);
13334					CSS.Normalizations.registered.outerWidth = getDimension("width");
13335					CSS.Normalizations.registered.outerHeight = getDimension("height");
13336				}
13337			},
13338			/************************
13339			 CSS Property Names
13340			 ************************/
13341
13342			Names: {
13343				/* Camelcase a property name into its JavaScript notation (e.g. "background-color" ==> "backgroundColor").
13344				 Camelcasing is used to normalize property names between and across calls. */
13345				camelCase: function(property) {
13346					return property.replace(/-(\w)/g, function(match, subMatch) {
13347						return subMatch.toUpperCase();
13348					});
13349				},
13350				/* For SVG elements, some properties (namely, dimensional ones) are GET/SET via the element's HTML attributes (instead of via CSS styles). */
13351				SVGAttribute: function(property) {
13352					var SVGAttributes = "width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2";
13353
13354					/* Certain browsers require an SVG transform to be applied as an attribute. (Otherwise, application via CSS is preferable due to 3D support.) */
13355					if (IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) {
13356						SVGAttributes += "|transform";
13357					}
13358
13359					return new RegExp("^(" + SVGAttributes + ")$", "i").test(property);
13360				},
13361				/* Determine whether a property should be set with a vendor prefix. */
13362				/* If a prefixed version of the property exists, return it. Otherwise, return the original property name.
13363				 If the property is not at all supported by the browser, return a false flag. */
13364				prefixCheck: function(property) {
13365					/* If this property has already been checked, return the cached value. */
13366					if (Velocity.State.prefixMatches[property]) {
13367						return [Velocity.State.prefixMatches[property], true];
13368					} else {
13369						var vendors = ["", "Webkit", "Moz", "ms", "O"];
13370
13371						for (var i = 0, vendorsLength = vendors.length; i < vendorsLength; i++) {
13372							var propertyPrefixed;
13373
13374							if (i === 0) {
13375								propertyPrefixed = property;
13376							} else {
13377								/* Capitalize the first letter of the property to conform to JavaScript vendor prefix notation (e.g. webkitFilter). */
13378								propertyPrefixed = vendors[i] + property.replace(/^\w/, function(match) {
13379									return match.toUpperCase();
13380								});
13381							}
13382
13383							/* Check if the browser supports this property as prefixed. */
13384							if (Type.isString(Velocity.State.prefixElement.style[propertyPrefixed])) {
13385								/* Cache the match. */
13386								Velocity.State.prefixMatches[property] = propertyPrefixed;
13387
13388								return [propertyPrefixed, true];
13389							}
13390						}
13391
13392						/* If the browser doesn't support this property in any form, include a false flag so that the caller can decide how to proceed. */
13393						return [property, false];
13394					}
13395				}
13396			},
13397			/************************
13398			 CSS Property Values
13399			 ************************/
13400
13401			Values: {
13402				/* Hex to RGB conversion. Copyright Tim Down: http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb */
13403				hexToRgb: function(hex) {
13404					var shortformRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i,
13405							longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,
13406							rgbParts;
13407
13408					hex = hex.replace(shortformRegex, function(m, r, g, b) {
13409						return r + r + g + g + b + b;
13410					});
13411
13412					rgbParts = longformRegex.exec(hex);
13413
13414					return rgbParts ? [parseInt(rgbParts[1], 16), parseInt(rgbParts[2], 16), parseInt(rgbParts[3], 16)] : [0, 0, 0];
13415				},
13416				isCSSNullValue: function(value) {
13417					/* The browser defaults CSS values that have not been set to either 0 or one of several possible null-value strings.
13418					 Thus, we check for both falsiness and these special strings. */
13419					/* Null-value checking is performed to default the special strings to 0 (for the sake of tweening) or their hook
13420					 templates as defined as CSS.Hooks (for the sake of hook injection/extraction). */
13421					/* Note: Chrome returns "rgba(0, 0, 0, 0)" for an undefined color whereas IE returns "transparent". */
13422					return (!value || /^(none|auto|transparent|(rgba\(0, ?0, ?0, ?0\)))$/i.test(value));
13423				},
13424				/* Retrieve a property's default unit type. Used for assigning a unit type when one is not supplied by the user. */
13425				getUnitType: function(property) {
13426					if (/^(rotate|skew)/i.test(property)) {
13427						return "deg";
13428					} else if (/(^(scale|scaleX|scaleY|scaleZ|alpha|flexGrow|flexHeight|zIndex|fontWeight)$)|((opacity|red|green|blue|alpha)$)/i.test(property)) {
13429						/* The above properties are unitless. */
13430						return "";
13431					} else {
13432						/* Default to px for all other properties. */
13433						return "px";
13434					}
13435				},
13436				/* HTML elements default to an associated display type when they're not set to display:none. */
13437				/* Note: This function is used for correctly setting the non-"none" display value in certain Velocity redirects, such as fadeIn/Out. */
13438				getDisplayType: function(element) {
13439					var tagName = element && element.tagName.toString().toLowerCase();
13440
13441					if (/^(b|big|i|small|tt|abbr|acronym|cite|code|dfn|em|kbd|strong|samp|var|a|bdo|br|img|map|object|q|script|span|sub|sup|button|input|label|select|textarea)$/i.test(tagName)) {
13442						return "inline";
13443					} else if (/^(li)$/i.test(tagName)) {
13444						return "list-item";
13445					} else if (/^(tr)$/i.test(tagName)) {
13446						return "table-row";
13447					} else if (/^(table)$/i.test(tagName)) {
13448						return "table";
13449					} else if (/^(tbody)$/i.test(tagName)) {
13450						return "table-row-group";
13451						/* Default to "block" when no match is found. */
13452					} else {
13453						return "block";
13454					}
13455				},
13456				/* The class add/remove functions are used to temporarily apply a "velocity-animating" class to elements while they're animating. */
13457				addClass: function(element, className) {
13458					if (element) {
13459						if (element.classList) {
13460							element.classList.add(className);
13461						} else if (Type.isString(element.className)) {
13462							// Element.className is around 15% faster then set/getAttribute
13463							element.className += (element.className.length ? " " : "") + className;
13464						} else {
13465							// Work around for IE strict mode animating SVG - and anything else that doesn't behave correctly - the same way jQuery does it
13466							var currentClass = element.getAttribute(IE <= 7 ? "className" : "class") || "";
13467
13468							element.setAttribute("class", currentClass + (currentClass ? " " : "") + className);
13469						}
13470					}
13471				},
13472				removeClass: function(element, className) {
13473					if (element) {
13474						if (element.classList) {
13475							element.classList.remove(className);
13476						} else if (Type.isString(element.className)) {
13477							// Element.className is around 15% faster then set/getAttribute
13478							// TODO: Need some jsperf tests on performance - can we get rid of the regex and maybe use split / array manipulation?
13479							element.className = element.className.toString().replace(new RegExp("(^|\\s)" + className.split(" ").join("|") + "(\\s|$)", "gi"), " ");
13480						} else {
13481							// Work around for IE strict mode animating SVG - and anything else that doesn't behave correctly - the same way jQuery does it
13482							var currentClass = element.getAttribute(IE <= 7 ? "className" : "class") || "";
13483
13484							element.setAttribute("class", currentClass.replace(new RegExp("(^|\s)" + className.split(" ").join("|") + "(\s|$)", "gi"), " "));
13485						}
13486					}
13487				}
13488			},
13489			/****************************
13490			 Style Getting & Setting
13491			 ****************************/
13492
13493			/* The singular getPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */
13494			getPropertyValue: function(element, property, rootPropertyValue, forceStyleLookup) {
13495				/* Get an element's computed property value. */
13496				/* Note: Retrieving the value of a CSS property cannot simply be performed by checking an element's
13497				 style attribute (which only reflects user-defined values). Instead, the browser must be queried for a property's
13498				 *computed* value. You can read more about getComputedStyle here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */
13499				function computePropertyValue(element, property) {
13500					/* When box-sizing isn't set to border-box, height and width style values are incorrectly computed when an
13501					 element's scrollbars are visible (which expands the element's dimensions). Thus, we defer to the more accurate
13502					 offsetHeight/Width property, which includes the total dimensions for interior, border, padding, and scrollbar.
13503					 We subtract border and padding to get the sum of interior + scrollbar. */
13504					var computedValue = 0;
13505
13506					/* IE<=8 doesn't support window.getComputedStyle, thus we defer to jQuery, which has an extensive array
13507					 of hacks to accurately retrieve IE8 property values. Re-implementing that logic here is not worth bloating the
13508					 codebase for a dying browser. The performance repercussions of using jQuery here are minimal since
13509					 Velocity is optimized to rarely (and sometimes never) query the DOM. Further, the $.css() codepath isn't that slow. */
13510					if (IE <= 8) {
13511						computedValue = $.css(element, property); /* GET */
13512						/* All other browsers support getComputedStyle. The returned live object reference is cached onto its
13513						 associated element so that it does not need to be refetched upon every GET. */
13514					} else {
13515						/* Browsers do not return height and width values for elements that are set to display:"none". Thus, we temporarily
13516						 toggle display to the element type's default value. */
13517						var toggleDisplay = false;
13518
13519						if (/^(width|height)$/.test(property) && CSS.getPropertyValue(element, "display") === 0) {
13520							toggleDisplay = true;
13521							CSS.setPropertyValue(element, "display", CSS.Values.getDisplayType(element));
13522						}
13523
13524						var revertDisplay = function() {
13525							if (toggleDisplay) {
13526								CSS.setPropertyValue(element, "display", "none");
13527							}
13528						};
13529
13530						if (!forceStyleLookup) {
13531							if (property === "height" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") {
13532								var contentBoxHeight = element.offsetHeight - (parseFloat(CSS.getPropertyValue(element, "borderTopWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "borderBottomWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingTop")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingBottom")) || 0);
13533								revertDisplay();
13534
13535								return contentBoxHeight;
13536							} else if (property === "width" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") {
13537								var contentBoxWidth = element.offsetWidth - (parseFloat(CSS.getPropertyValue(element, "borderLeftWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "borderRightWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingLeft")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingRight")) || 0);
13538								revertDisplay();
13539
13540								return contentBoxWidth;
13541							}
13542						}
13543
13544						var computedStyle;
13545
13546						/* For elements that Velocity hasn't been called on directly (e.g. when Velocity queries the DOM on behalf
13547						 of a parent of an element its animating), perform a direct getComputedStyle lookup since the object isn't cached. */
13548						if (Data(element) === undefined) {
13549							computedStyle = window.getComputedStyle(element, null); /* GET */
13550							/* If the computedStyle object has yet to be cached, do so now. */
13551						} else if (!Data(element).computedStyle) {
13552							computedStyle = Data(element).computedStyle = window.getComputedStyle(element, null); /* GET */
13553							/* If computedStyle is cached, use it. */
13554						} else {
13555							computedStyle = Data(element).computedStyle;
13556						}
13557
13558						/* IE and Firefox do not return a value for the generic borderColor -- they only return individual values for each border side's color.
13559						 Also, in all browsers, when border colors aren't all the same, a compound value is returned that Velocity isn't setup to parse.
13560						 So, as a polyfill for querying individual border side colors, we just return the top border's color and animate all borders from that value. */
13561						if (property === "borderColor") {
13562							property = "borderTopColor";
13563						}
13564
13565						/* IE9 has a bug in which the "filter" property must be accessed from computedStyle using the getPropertyValue method
13566						 instead of a direct property lookup. The getPropertyValue method is slower than a direct lookup, which is why we avoid it by default. */
13567						if (IE === 9 && property === "filter") {
13568							computedValue = computedStyle.getPropertyValue(property); /* GET */
13569						} else {
13570							computedValue = computedStyle[property];
13571						}
13572
13573						/* Fall back to the property's style value (if defined) when computedValue returns nothing,
13574						 which can happen when the element hasn't been painted. */
13575						if (computedValue === "" || computedValue === null) {
13576							computedValue = element.style[property];
13577						}
13578
13579						revertDisplay();
13580					}
13581
13582					/* For top, right, bottom, and left (TRBL) values that are set to "auto" on elements of "fixed" or "absolute" position,
13583					 defer to jQuery for converting "auto" to a numeric value. (For elements with a "static" or "relative" position, "auto" has the same
13584					 effect as being set to 0, so no conversion is necessary.) */
13585					/* An example of why numeric conversion is necessary: When an element with "position:absolute" has an untouched "left"
13586					 property, which reverts to "auto", left's value is 0 relative to its parent element, but is often non-zero relative
13587					 to its *containing* (not parent) element, which is the nearest "position:relative" ancestor or the viewport (and always the viewport in the case of "position:fixed"). */
13588					if (computedValue === "auto" && /^(top|right|bottom|left)$/i.test(property)) {
13589						var position = computePropertyValue(element, "position"); /* GET */
13590
13591						/* For absolute positioning, jQuery's $.position() only returns values for top and left;
13592						 right and bottom will have their "auto" value reverted to 0. */
13593						/* Note: A jQuery object must be created here since jQuery doesn't have a low-level alias for $.position().
13594						 Not a big deal since we're currently in a GET batch anyway. */
13595						if (position === "fixed" || (position === "absolute" && /top|left/i.test(property))) {
13596							/* Note: jQuery strips the pixel unit from its returned values; we re-add it here to conform with computePropertyValue's behavior. */
13597							computedValue = $(element).position()[property] + "px"; /* GET */
13598						}
13599					}
13600
13601					return computedValue;
13602				}
13603
13604				var propertyValue;
13605
13606				/* If this is a hooked property (e.g. "clipLeft" instead of the root property of "clip"),
13607				 extract the hook's value from a normalized rootPropertyValue using CSS.Hooks.extractValue(). */
13608				if (CSS.Hooks.registered[property]) {
13609					var hook = property,
13610							hookRoot = CSS.Hooks.getRoot(hook);
13611
13612					/* If a cached rootPropertyValue wasn't passed in (which Velocity always attempts to do in order to avoid requerying the DOM),
13613					 query the DOM for the root property's value. */
13614					if (rootPropertyValue === undefined) {
13615						/* Since the browser is now being directly queried, use the official post-prefixing property name for this lookup. */
13616						rootPropertyValue = CSS.getPropertyValue(element, CSS.Names.prefixCheck(hookRoot)[0]); /* GET */
13617					}
13618
13619					/* If this root has a normalization registered, peform the associated normalization extraction. */
13620					if (CSS.Normalizations.registered[hookRoot]) {
13621						rootPropertyValue = CSS.Normalizations.registered[hookRoot]("extract", element, rootPropertyValue);
13622					}
13623
13624					/* Extract the hook's value. */
13625					propertyValue = CSS.Hooks.extractValue(hook, rootPropertyValue);
13626
13627					/* If this is a normalized property (e.g. "opacity" becomes "filter" in <=IE8) or "translateX" becomes "transform"),
13628					 normalize the property's name and value, and handle the special case of transforms. */
13629					/* Note: Normalizing a property is mutually exclusive from hooking a property since hook-extracted values are strictly
13630					 numerical and therefore do not require normalization extraction. */
13631				} else if (CSS.Normalizations.registered[property]) {
13632					var normalizedPropertyName,
13633							normalizedPropertyValue;
13634
13635					normalizedPropertyName = CSS.Normalizations.registered[property]("name", element);
13636
13637					/* Transform values are calculated via normalization extraction (see below), which checks against the element's transformCache.
13638					 At no point do transform GETs ever actually query the DOM; initial stylesheet values are never processed.
13639					 This is because parsing 3D transform matrices is not always accurate and would bloat our codebase;
13640					 thus, normalization extraction defaults initial transform values to their zero-values (e.g. 1 for scaleX and 0 for translateX). */
13641					if (normalizedPropertyName !== "transform") {
13642						normalizedPropertyValue = computePropertyValue(element, CSS.Names.prefixCheck(normalizedPropertyName)[0]); /* GET */
13643
13644						/* If the value is a CSS null-value and this property has a hook template, use that zero-value template so that hooks can be extracted from it. */
13645						if (CSS.Values.isCSSNullValue(normalizedPropertyValue) && CSS.Hooks.templates[property]) {
13646							normalizedPropertyValue = CSS.Hooks.templates[property][1];
13647						}
13648					}
13649
13650					propertyValue = CSS.Normalizations.registered[property]("extract", element, normalizedPropertyValue);
13651				}
13652
13653				/* If a (numeric) value wasn't produced via hook extraction or normalization, query the DOM. */
13654				if (!/^[\d-]/.test(propertyValue)) {
13655					/* For SVG elements, dimensional properties (which SVGAttribute() detects) are tweened via
13656					 their HTML attribute values instead of their CSS style values. */
13657					var data = Data(element);
13658
13659					if (data && data.isSVG && CSS.Names.SVGAttribute(property)) {
13660						/* Since the height/width attribute values must be set manually, they don't reflect computed values.
13661						 Thus, we use use getBBox() to ensure we always get values for elements with undefined height/width attributes. */
13662						if (/^(height|width)$/i.test(property)) {
13663							/* Firefox throws an error if .getBBox() is called on an SVG that isn't attached to the DOM. */
13664							try {
13665								propertyValue = element.getBBox()[property];
13666							} catch (error) {
13667								propertyValue = 0;
13668							}
13669							/* Otherwise, access the attribute value directly. */
13670						} else {
13671							propertyValue = element.getAttribute(property);
13672						}
13673					} else {
13674						propertyValue = computePropertyValue(element, CSS.Names.prefixCheck(property)[0]); /* GET */
13675					}
13676				}
13677
13678				/* Since property lookups are for animation purposes (which entails computing the numeric delta between start and end values),
13679				 convert CSS null-values to an integer of value 0. */
13680				if (CSS.Values.isCSSNullValue(propertyValue)) {
13681					propertyValue = 0;
13682				}
13683
13684				if (Velocity.debug >= 2) {
13685					console.log("Get " + property + ": " + propertyValue);
13686				}
13687
13688				return propertyValue;
13689			},
13690			/* The singular setPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */
13691			setPropertyValue: function(element, property, propertyValue, rootPropertyValue, scrollData) {
13692				var propertyName = property;
13693
13694				/* In order to be subjected to call options and element queueing, scroll animation is routed through Velocity as if it were a standard CSS property. */
13695				if (property === "scroll") {
13696					/* If a container option is present, scroll the container instead of the browser window. */
13697					if (scrollData.container) {
13698						scrollData.container["scroll" + scrollData.direction] = propertyValue;
13699						/* Otherwise, Velocity defaults to scrolling the browser window. */
13700					} else {
13701						if (scrollData.direction === "Left") {
13702							window.scrollTo(propertyValue, scrollData.alternateValue);
13703						} else {
13704							window.scrollTo(scrollData.alternateValue, propertyValue);
13705						}
13706					}
13707				} else {
13708					/* Transforms (translateX, rotateZ, etc.) are applied to a per-element transformCache object, which is manually flushed via flushTransformCache().
13709					 Thus, for now, we merely cache transforms being SET. */
13710					if (CSS.Normalizations.registered[property] && CSS.Normalizations.registered[property]("name", element) === "transform") {
13711						/* Perform a normalization injection. */
13712						/* Note: The normalization logic handles the transformCache updating. */
13713						CSS.Normalizations.registered[property]("inject", element, propertyValue);
13714
13715						propertyName = "transform";
13716						propertyValue = Data(element).transformCache[property];
13717					} else {
13718						/* Inject hooks. */
13719						if (CSS.Hooks.registered[property]) {
13720							var hookName = property,
13721									hookRoot = CSS.Hooks.getRoot(property);
13722
13723							/* If a cached rootPropertyValue was not provided, query the DOM for the hookRoot's current value. */
13724							rootPropertyValue = rootPropertyValue || CSS.getPropertyValue(element, hookRoot); /* GET */
13725
13726							propertyValue = CSS.Hooks.injectValue(hookName, propertyValue, rootPropertyValue);
13727							property = hookRoot;
13728						}
13729
13730						/* Normalize names and values. */
13731						if (CSS.Normalizations.registered[property]) {
13732							propertyValue = CSS.Normalizations.registered[property]("inject", element, propertyValue);
13733							property = CSS.Normalizations.registered[property]("name", element);
13734						}
13735
13736						/* Assign the appropriate vendor prefix before performing an official style update. */
13737						propertyName = CSS.Names.prefixCheck(property)[0];
13738
13739						/* A try/catch is used for IE<=8, which throws an error when "invalid" CSS values are set, e.g. a negative width.
13740						 Try/catch is avoided for other browsers since it incurs a performance overhead. */
13741						if (IE <= 8) {
13742							try {
13743								element.style[propertyName] = propertyValue;
13744							} catch (error) {
13745								if (Velocity.debug) {
13746									console.log("Browser does not support [" + propertyValue + "] for [" + propertyName + "]");
13747								}
13748							}
13749							/* SVG elements have their dimensional properties (width, height, x, y, cx, etc.) applied directly as attributes instead of as styles. */
13750							/* Note: IE8 does not support SVG elements, so it's okay that we skip it for SVG animation. */
13751						} else {
13752							var data = Data(element);
13753
13754							if (data && data.isSVG && CSS.Names.SVGAttribute(property)) {
13755								/* Note: For SVG attributes, vendor-prefixed property names are never used. */
13756								/* Note: Not all CSS properties can be animated via attributes, but the browser won't throw an error for unsupported properties. */
13757								element.setAttribute(property, propertyValue);
13758							} else {
13759								element.style[propertyName] = propertyValue;
13760							}
13761						}
13762
13763						if (Velocity.debug >= 2) {
13764							console.log("Set " + property + " (" + propertyName + "): " + propertyValue);
13765						}
13766					}
13767				}
13768
13769				/* Return the normalized property name and value in case the caller wants to know how these values were modified before being applied to the DOM. */
13770				return [propertyName, propertyValue];
13771			},
13772			/* To increase performance by batching transform updates into a single SET, transforms are not directly applied to an element until flushTransformCache() is called. */
13773			/* Note: Velocity applies transform properties in the same order that they are chronogically introduced to the element's CSS styles. */
13774			flushTransformCache: function(element) {
13775				var transformString = "",
13776						data = Data(element);
13777
13778				/* Certain browsers require that SVG transforms be applied as an attribute. However, the SVG transform attribute takes a modified version of CSS's transform string
13779				 (units are dropped and, except for skewX/Y, subproperties are merged into their master property -- e.g. scaleX and scaleY are merged into scale(X Y). */
13780				if ((IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) && data && data.isSVG) {
13781					/* Since transform values are stored in their parentheses-wrapped form, we use a helper function to strip out their numeric values.
13782					 Further, SVG transform properties only take unitless (representing pixels) values, so it's okay that parseFloat() strips the unit suffixed to the float value. */
13783					var getTransformFloat = function(transformProperty) {
13784						return parseFloat(CSS.getPropertyValue(element, transformProperty));
13785					};
13786
13787					/* Create an object to organize all the transforms that we'll apply to the SVG element. To keep the logic simple,
13788					 we process *all* transform properties -- even those that may not be explicitly applied (since they default to their zero-values anyway). */
13789					var SVGTransforms = {
13790						translate: [getTransformFloat("translateX"), getTransformFloat("translateY")],
13791						skewX: [getTransformFloat("skewX")], skewY: [getTransformFloat("skewY")],
13792						/* If the scale property is set (non-1), use that value for the scaleX and scaleY values
13793						 (this behavior mimics the result of animating all these properties at once on HTML elements). */
13794						scale: getTransformFloat("scale") !== 1 ? [getTransformFloat("scale"), getTransformFloat("scale")] : [getTransformFloat("scaleX"), getTransformFloat("scaleY")],
13795						/* Note: SVG's rotate transform takes three values: rotation degrees followed by the X and Y values
13796						 defining the rotation's origin point. We ignore the origin values (default them to 0). */
13797						rotate: [getTransformFloat("rotateZ"), 0, 0]
13798					};
13799
13800					/* Iterate through the transform properties in the user-defined property map order.
13801					 (This mimics the behavior of non-SVG transform animation.) */
13802					$.each(Data(element).transformCache, function(transformName) {
13803						/* Except for with skewX/Y, revert the axis-specific transform subproperties to their axis-free master
13804						 properties so that they match up with SVG's accepted transform properties. */
13805						if (/^translate/i.test(transformName)) {
13806							transformName = "translate";
13807						} else if (/^scale/i.test(transformName)) {
13808							transformName = "scale";
13809						} else if (/^rotate/i.test(transformName)) {
13810							transformName = "rotate";
13811						}
13812
13813						/* Check that we haven't yet deleted the property from the SVGTransforms container. */
13814						if (SVGTransforms[transformName]) {
13815							/* Append the transform property in the SVG-supported transform format. As per the spec, surround the space-delimited values in parentheses. */
13816							transformString += transformName + "(" + SVGTransforms[transformName].join(" ") + ")" + " ";
13817
13818							/* After processing an SVG transform property, delete it from the SVGTransforms container so we don't
13819							 re-insert the same master property if we encounter another one of its axis-specific properties. */
13820							delete SVGTransforms[transformName];
13821						}
13822					});
13823				} else {
13824					var transformValue,
13825							perspective;
13826
13827					/* Transform properties are stored as members of the transformCache object. Concatenate all the members into a string. */
13828					$.each(Data(element).transformCache, function(transformName) {
13829						transformValue = Data(element).transformCache[transformName];
13830
13831						/* Transform's perspective subproperty must be set first in order to take effect. Store it temporarily. */
13832						if (transformName === "transformPerspective") {
13833							perspective = transformValue;
13834							return true;
13835						}
13836
13837						/* IE9 only supports one rotation type, rotateZ, which it refers to as "rotate". */
13838						if (IE === 9 && transformName === "rotateZ") {
13839							transformName = "rotate";
13840						}
13841
13842						transformString += transformName + transformValue + " ";
13843					});
13844
13845					/* If present, set the perspective subproperty first. */
13846					if (perspective) {
13847						transformString = "perspective" + perspective + " " + transformString;
13848					}
13849				}
13850
13851				CSS.setPropertyValue(element, "transform", transformString);
13852			}
13853		};
13854
13855		/* Register hooks and normalizations. */
13856		CSS.Hooks.register();
13857		CSS.Normalizations.register();
13858
13859		/* Allow hook setting in the same fashion as jQuery's $.css(). */
13860		Velocity.hook = function(elements, arg2, arg3) {
13861			var value;
13862
13863			elements = sanitizeElements(elements);
13864
13865			$.each(elements, function(i, element) {
13866				/* Initialize Velocity's per-element data cache if this element hasn't previously been animated. */
13867				if (Data(element) === undefined) {
13868					Velocity.init(element);
13869				}
13870
13871				/* Get property value. If an element set was passed in, only return the value for the first element. */
13872				if (arg3 === undefined) {
13873					if (value === undefined) {
13874						value = CSS.getPropertyValue(element, arg2);
13875					}
13876					/* Set property value. */
13877				} else {
13878					/* sPV returns an array of the normalized propertyName/propertyValue pair used to update the DOM. */
13879					var adjustedSet = CSS.setPropertyValue(element, arg2, arg3);
13880
13881					/* Transform properties don't automatically set. They have to be flushed to the DOM. */
13882					if (adjustedSet[0] === "transform") {
13883						Velocity.CSS.flushTransformCache(element);
13884					}
13885
13886					value = adjustedSet;
13887				}
13888			});
13889
13890			return value;
13891		};
13892
13893		/*****************
13894		 Animation
13895		 *****************/
13896
13897		var animate = function() {
13898			var opts;
13899
13900			/******************
13901			 Call Chain
13902			 ******************/
13903
13904			/* Logic for determining what to return to the call stack when exiting out of Velocity. */
13905			function getChain() {
13906				/* If we are using the utility function, attempt to return this call's promise. If no promise library was detected,
13907				 default to null instead of returning the targeted elements so that utility function's return value is standardized. */
13908				if (isUtility) {
13909					return promiseData.promise || null;
13910					/* Otherwise, if we're using $.fn, return the jQuery-/Zepto-wrapped element set. */
13911				} else {
13912					return elementsWrapped;
13913				}
13914			}
13915
13916			/*************************
13917			 Arguments Assignment
13918			 *************************/
13919
13920			/* To allow for expressive CoffeeScript code, Velocity supports an alternative syntax in which "elements" (or "e"), "properties" (or "p"), and "options" (or "o")
13921			 objects are defined on a container object that's passed in as Velocity's sole argument. */
13922			/* Note: Some browsers automatically populate arguments with a "properties" object. We detect it by checking for its default "names" property. */
13923			var syntacticSugar = (arguments[0] && (arguments[0].p || (($.isPlainObject(arguments[0].properties) && !arguments[0].properties.names) || Type.isString(arguments[0].properties)))),
13924					/* Whether Velocity was called via the utility function (as opposed to on a jQuery/Zepto object). */
13925					isUtility,
13926					/* When Velocity is called via the utility function ($.Velocity()/Velocity()), elements are explicitly
13927					 passed in as the first parameter. Thus, argument positioning varies. We normalize them here. */
13928					elementsWrapped,
13929					argumentIndex;
13930
13931			var elements,
13932					propertiesMap,
13933					options;
13934
13935			/* Detect jQuery/Zepto elements being animated via the $.fn method. */
13936			if (Type.isWrapped(this)) {
13937				isUtility = false;
13938
13939				argumentIndex = 0;
13940				elements = this;
13941				elementsWrapped = this;
13942				/* Otherwise, raw elements are being animated via the utility function. */
13943			} else {
13944				isUtility = true;
13945
13946				argumentIndex = 1;
13947				elements = syntacticSugar ? (arguments[0].elements || arguments[0].e) : arguments[0];
13948			}
13949
13950			/***************
13951			 Promises
13952			 ***************/
13953
13954			var promiseData = {
13955				promise: null,
13956				resolver: null,
13957				rejecter: null
13958			};
13959
13960			/* If this call was made via the utility function (which is the default method of invocation when jQuery/Zepto are not being used), and if
13961			 promise support was detected, create a promise object for this call and store references to its resolver and rejecter methods. The resolve
13962			 method is used when a call completes naturally or is prematurely stopped by the user. In both cases, completeCall() handles the associated
13963			 call cleanup and promise resolving logic. The reject method is used when an invalid set of arguments is passed into a Velocity call. */
13964			/* Note: Velocity employs a call-based queueing architecture, which means that stopping an animating element actually stops the full call that
13965			 triggered it -- not that one element exclusively. Similarly, there is one promise per call, and all elements targeted by a Velocity call are
13966			 grouped together for the purposes of resolving and rejecting a promise. */
13967			if (isUtility && Velocity.Promise) {
13968				promiseData.promise = new Velocity.Promise(function(resolve, reject) {
13969					promiseData.resolver = resolve;
13970					promiseData.rejecter = reject;
13971				});
13972			}
13973
13974			if (syntacticSugar) {
13975				propertiesMap = arguments[0].properties || arguments[0].p;
13976				options = arguments[0].options || arguments[0].o;
13977			} else {
13978				propertiesMap = arguments[argumentIndex];
13979				options = arguments[argumentIndex + 1];
13980			}
13981
13982			elements = sanitizeElements(elements);
13983
13984			if (!elements) {
13985				if (promiseData.promise) {
13986					if (!propertiesMap || !options || options.promiseRejectEmpty !== false) {
13987						promiseData.rejecter();
13988					} else {
13989						promiseData.resolver();
13990					}
13991				}
13992				return;
13993			}
13994
13995			/* The length of the element set (in the form of a nodeList or an array of elements) is defaulted to 1 in case a
13996			 single raw DOM element is passed in (which doesn't contain a length property). */
13997			var elementsLength = elements.length,
13998					elementsIndex = 0;
13999
14000			/***************************
14001			 Argument Overloading
14002			 ***************************/
14003
14004			/* Support is included for jQuery's argument overloading: $.animate(propertyMap [, duration] [, easing] [, complete]).
14005			 Overloading is detected by checking for the absence of an object being passed into options. */
14006			/* Note: The stop/finish/pause/resume actions do not accept animation options, and are therefore excluded from this check. */
14007			if (!/^(stop|finish|finishAll|pause|resume)$/i.test(propertiesMap) && !$.isPlainObject(options)) {
14008				/* The utility function shifts all arguments one position to the right, so we adjust for that offset. */
14009				var startingArgumentPosition = argumentIndex + 1;
14010
14011				options = {};
14012
14013				/* Iterate through all options arguments */
14014				for (var i = startingArgumentPosition; i < arguments.length; i++) {
14015					/* Treat a number as a duration. Parse it out. */
14016					/* Note: The following RegEx will return true if passed an array with a number as its first item.
14017					 Thus, arrays are skipped from this check. */
14018					if (!Type.isArray(arguments[i]) && (/^(fast|normal|slow)$/i.test(arguments[i]) || /^\d/.test(arguments[i]))) {
14019						options.duration = arguments[i];
14020						/* Treat strings and arrays as easings. */
14021					} else if (Type.isString(arguments[i]) || Type.isArray(arguments[i])) {
14022						options.easing = arguments[i];
14023						/* Treat a function as a complete callback. */
14024					} else if (Type.isFunction(arguments[i])) {
14025						options.complete = arguments[i];
14026					}
14027				}
14028			}
14029
14030			/*********************
14031			 Action Detection
14032			 *********************/
14033
14034			/* Velocity's behavior is categorized into "actions": Elements can either be specially scrolled into view,
14035			 or they can be started, stopped, paused, resumed, or reversed . If a literal or referenced properties map is passed in as Velocity's
14036			 first argument, the associated action is "start". Alternatively, "scroll", "reverse", "pause", "resume" or "stop" can be passed in 
14037			 instead of a properties map. */
14038			var action;
14039
14040			switch (propertiesMap) {
14041				case "scroll":
14042					action = "scroll";
14043					break;
14044
14045				case "reverse":
14046					action = "reverse";
14047					break;
14048
14049				case "pause":
14050
14051					/*******************
14052					 Action: Pause
14053					 *******************/
14054
14055					var currentTime = (new Date()).getTime();
14056
14057					/* Handle delay timers */
14058					$.each(elements, function(i, element) {
14059						pauseDelayOnElement(element, currentTime);
14060					});
14061
14062					/* Pause and Resume are call-wide (not on a per element basis). Thus, calling pause or resume on a 
14063					 single element will cause any calls that containt tweens for that element to be paused/resumed
14064					 as well. */
14065
14066					/* Iterate through all calls and pause any that contain any of our elements */
14067					$.each(Velocity.State.calls, function(i, activeCall) {
14068
14069						var found = false;
14070						/* Inactive calls are set to false by the logic inside completeCall(). Skip them. */
14071						if (activeCall) {
14072							/* Iterate through the active call's targeted elements. */
14073							$.each(activeCall[1], function(k, activeElement) {
14074								var queueName = (options === undefined) ? "" : options;
14075
14076								if (queueName !== true && (activeCall[2].queue !== queueName) && !(options === undefined && activeCall[2].queue === false)) {
14077									return true;
14078								}
14079
14080								/* Iterate through the calls targeted by the stop command. */
14081								$.each(elements, function(l, element) {
14082									/* Check that this call was applied to the target element. */
14083									if (element === activeElement) {
14084
14085										/* Set call to paused */
14086										activeCall[5] = {
14087											resume: false
14088										};
14089
14090										/* Once we match an element, we can bounce out to the next call entirely */
14091										found = true;
14092										return false;
14093									}
14094								});
14095
14096								/* Proceed to check next call if we have already matched */
14097								if (found) {
14098									return false;
14099								}
14100							});
14101						}
14102
14103					});
14104
14105					/* Since pause creates no new tweens, exit out of Velocity. */
14106					return getChain();
14107
14108				case "resume":
14109
14110					/*******************
14111					 Action: Resume
14112					 *******************/
14113
14114					/* Handle delay timers */
14115					$.each(elements, function(i, element) {
14116						resumeDelayOnElement(element, currentTime);
14117					});
14118
14119					/* Pause and Resume are call-wide (not on a per elemnt basis). Thus, calling pause or resume on a 
14120					 single element will cause any calls that containt tweens for that element to be paused/resumed
14121					 as well. */
14122
14123					/* Iterate through all calls and pause any that contain any of our elements */
14124					$.each(Velocity.State.calls, function(i, activeCall) {
14125						var found = false;
14126						/* Inactive calls are set to false by the logic inside completeCall(). Skip them. */
14127						if (activeCall) {
14128							/* Iterate through the active call's targeted elements. */
14129							$.each(activeCall[1], function(k, activeElement) {
14130								var queueName = (options === undefined) ? "" : options;
14131
14132								if (queueName !== true && (activeCall[2].queue !== queueName) && !(options === undefined && activeCall[2].queue === false)) {
14133									return true;
14134								}
14135
14136								/* Skip any calls that have never been paused */
14137								if (!activeCall[5]) {
14138									return true;
14139								}
14140
14141								/* Iterate through the calls targeted by the stop command. */
14142								$.each(elements, function(l, element) {
14143									/* Check that this call was applied to the target element. */
14144									if (element === activeElement) {
14145
14146										/* Flag a pause object to be resumed, which will occur during the next tick. In
14147										 addition, the pause object will at that time be deleted */
14148										activeCall[5].resume = true;
14149
14150										/* Once we match an element, we can bounce out to the next call entirely */
14151										found = true;
14152										return false;
14153									}
14154								});
14155
14156								/* Proceed to check next call if we have already matched */
14157								if (found) {
14158									return false;
14159								}
14160							});
14161						}
14162
14163					});
14164
14165					/* Since resume creates no new tweens, exit out of Velocity. */
14166					return getChain();
14167
14168				case "finish":
14169				case "finishAll":
14170				case "stop":
14171					/*******************
14172					 Action: Stop
14173					 *******************/
14174
14175					/* Clear the currently-active delay on each targeted element. */
14176					$.each(elements, function(i, element) {
14177						if (Data(element) && Data(element).delayTimer) {
14178							/* Stop the timer from triggering its cached next() function. */
14179							clearTimeout(Data(element).delayTimer.setTimeout);
14180
14181							/* Manually call the next() function so that the subsequent queue items can progress. */
14182							if (Data(element).delayTimer.next) {
14183								Data(element).delayTimer.next();
14184							}
14185
14186							delete Data(element).delayTimer;
14187						}
14188
14189						/* If we want to finish everything in the queue, we have to iterate through it
14190						 and call each function. This will make them active calls below, which will
14191						 cause them to be applied via the duration setting. */
14192						if (propertiesMap === "finishAll" && (options === true || Type.isString(options))) {
14193							/* Iterate through the items in the element's queue. */
14194							$.each($.queue(element, Type.isString(options) ? options : ""), function(_, item) {
14195								/* The queue array can contain an "inprogress" string, which we skip. */
14196								if (Type.isFunction(item)) {
14197									item();
14198								}
14199							});
14200
14201							/* Clearing the $.queue() array is achieved by resetting it to []. */
14202							$.queue(element, Type.isString(options) ? options : "", []);
14203						}
14204					});
14205
14206					var callsToStop = [];
14207
14208					/* When the stop action is triggered, the elements' currently active call is immediately stopped. The active call might have
14209					 been applied to multiple elements, in which case all of the call's elements will be stopped. When an element
14210					 is stopped, the next item in its animation queue is immediately triggered. */
14211					/* An additional argument may be passed in to clear an element's remaining queued calls. Either true (which defaults to the "fx" queue)
14212					 or a custom queue string can be passed in. */
14213					/* Note: The stop command runs prior to Velocity's Queueing phase since its behavior is intended to take effect *immediately*,
14214					 regardless of the element's current queue state. */
14215
14216					/* Iterate through every active call. */
14217					$.each(Velocity.State.calls, function(i, activeCall) {
14218						/* Inactive calls are set to false by the logic inside completeCall(). Skip them. */
14219						if (activeCall) {
14220							/* Iterate through the active call's targeted elements. */
14221							$.each(activeCall[1], function(k, activeElement) {
14222								/* If true was passed in as a secondary argument, clear absolutely all calls on this element. Otherwise, only
14223								 clear calls associated with the relevant queue. */
14224								/* Call stopping logic works as follows:
14225								 - options === true --> stop current default queue calls (and queue:false calls), including remaining queued ones.
14226								 - options === undefined --> stop current queue:"" call and all queue:false calls.
14227								 - options === false --> stop only queue:false calls.
14228								 - options === "custom" --> stop current queue:"custom" call, including remaining queued ones (there is no functionality to only clear the currently-running queue:"custom" call). */
14229								var queueName = (options === undefined) ? "" : options;
14230
14231								if (queueName !== true && (activeCall[2].queue !== queueName) && !(options === undefined && activeCall[2].queue === false)) {
14232									return true;
14233								}
14234
14235								/* Iterate through the calls targeted by the stop command. */
14236								$.each(elements, function(l, element) {
14237									/* Check that this call was applied to the target element. */
14238									if (element === activeElement) {
14239										/* Optionally clear the remaining queued calls. If we're doing "finishAll" this won't find anything,
14240										 due to the queue-clearing above. */
14241										if (options === true || Type.isString(options)) {
14242											/* Iterate through the items in the element's queue. */
14243											$.each($.queue(element, Type.isString(options) ? options : ""), function(_, item) {
14244												/* The queue array can contain an "inprogress" string, which we skip. */
14245												if (Type.isFunction(item)) {
14246													/* Pass the item's callback a flag indicating that we want to abort from the queue call.
14247													 (Specifically, the queue will resolve the call's associated promise then abort.)  */
14248													item(null, true);
14249												}
14250											});
14251
14252											/* Clearing the $.queue() array is achieved by resetting it to []. */
14253											$.queue(element, Type.isString(options) ? options : "", []);
14254										}
14255
14256										if (propertiesMap === "stop") {
14257											/* Since "reverse" uses cached start values (the previous call's endValues), these values must be
14258											 changed to reflect the final value that the elements were actually tweened to. */
14259											/* Note: If only queue:false animations are currently running on an element, it won't have a tweensContainer
14260											 object. Also, queue:false animations can't be reversed. */
14261											var data = Data(element);
14262											if (data && data.tweensContainer && queueName !== false) {
14263												$.each(data.tweensContainer, function(m, activeTween) {
14264													activeTween.endValue = activeTween.currentValue;
14265												});
14266											}
14267
14268											callsToStop.push(i);
14269										} else if (propertiesMap === "finish" || propertiesMap === "finishAll") {
14270											/* To get active tweens to finish immediately, we forcefully shorten their durations to 1ms so that
14271											 they finish upon the next rAf tick then proceed with normal call completion logic. */
14272											activeCall[2].duration = 1;
14273										}
14274									}
14275								});
14276							});
14277						}
14278					});
14279
14280					/* Prematurely call completeCall() on each matched active call. Pass an additional flag for "stop" to indicate
14281					 that the complete callback and display:none setting should be skipped since we're completing prematurely. */
14282					if (propertiesMap === "stop") {
14283						$.each(callsToStop, function(i, j) {
14284							completeCall(j, true);
14285						});
14286
14287						if (promiseData.promise) {
14288							/* Immediately resolve the promise associated with this stop call since stop runs synchronously. */
14289							promiseData.resolver(elements);
14290						}
14291					}
14292
14293					/* Since we're stopping, and not proceeding with queueing, exit out of Velocity. */
14294					return getChain();
14295
14296				default:
14297					/* Treat a non-empty plain object as a literal properties map. */
14298					if ($.isPlainObject(propertiesMap) && !Type.isEmptyObject(propertiesMap)) {
14299						action = "start";
14300
14301						/****************
14302						 Redirects
14303						 ****************/
14304
14305						/* Check if a string matches a registered redirect (see Redirects above). */
14306					} else if (Type.isString(propertiesMap) && Velocity.Redirects[propertiesMap]) {
14307						opts = $.extend({}, options);
14308
14309						var durationOriginal = opts.duration,
14310								delayOriginal = opts.delay || 0;
14311
14312						/* If the backwards option was passed in, reverse the element set so that elements animate from the last to the first. */
14313						if (opts.backwards === true) {
14314							elements = $.extend(true, [], elements).reverse();
14315						}
14316
14317						/* Individually trigger the redirect for each element in the set to prevent users from having to handle iteration logic in their redirect. */
14318						$.each(elements, function(elementIndex, element) {
14319							/* If the stagger option was passed in, successively delay each element by the stagger value (in ms). Retain the original delay value. */
14320							if (parseFloat(opts.stagger)) {
14321								opts.delay = delayOriginal + (parseFloat(opts.stagger) * elementIndex);
14322							} else if (Type.isFunction(opts.stagger)) {
14323								opts.delay = delayOriginal + opts.stagger.call(element, elementIndex, elementsLength);
14324							}
14325
14326							/* If the drag option was passed in, successively increase/decrease (depending on the presense of opts.backwards)
14327							 the duration of each element's animation, using floors to prevent producing very short durations. */
14328							if (opts.drag) {
14329								/* Default the duration of UI pack effects (callouts and transitions) to 1000ms instead of the usual default duration of 400ms. */
14330								opts.duration = parseFloat(durationOriginal) || (/^(callout|transition)/.test(propertiesMap) ? 1000 : DURATION_DEFAULT);
14331
14332								/* For each element, take the greater duration of: A) animation completion percentage relative to the original duration,
14333								 B) 75% of the original duration, or C) a 200ms fallback (in case duration is already set to a low value).
14334								 The end result is a baseline of 75% of the redirect's duration that increases/decreases as the end of the element set is approached. */
14335								opts.duration = Math.max(opts.duration * (opts.backwards ? 1 - elementIndex / elementsLength : (elementIndex + 1) / elementsLength), opts.duration * 0.75, 200);
14336							}
14337
14338							/* Pass in the call's opts object so that the redirect can optionally extend it. It defaults to an empty object instead of null to
14339							 reduce the opts checking logic required inside the redirect. */
14340							Velocity.Redirects[propertiesMap].call(element, element, opts || {}, elementIndex, elementsLength, elements, promiseData.promise ? promiseData : undefined);
14341						});
14342
14343						/* Since the animation logic resides within the redirect's own code, abort the remainder of this call.
14344						 (The performance overhead up to this point is virtually non-existant.) */
14345						/* Note: The jQuery call chain is kept intact by returning the complete element set. */
14346						return getChain();
14347					} else {
14348						var abortError = "Velocity: First argument (" + propertiesMap + ") was not a property map, a known action, or a registered redirect. Aborting.";
14349
14350						if (promiseData.promise) {
14351							promiseData.rejecter(new Error(abortError));
14352						} else if (window.console) {
14353							console.log(abortError);
14354						}
14355
14356						return getChain();
14357					}
14358			}
14359
14360			/**************************
14361			 Call-Wide Variables
14362			 **************************/
14363
14364			/* A container for CSS unit conversion ratios (e.g. %, rem, and em ==> px) that is used to cache ratios across all elements
14365			 being animated in a single Velocity call. Calculating unit ratios necessitates DOM querying and updating, and is therefore
14366			 avoided (via caching) wherever possible. This container is call-wide instead of page-wide to avoid the risk of using stale
14367			 conversion metrics across Velocity animations that are not immediately consecutively chained. */
14368			var callUnitConversionData = {
14369				lastParent: null,
14370				lastPosition: null,
14371				lastFontSize: null,
14372				lastPercentToPxWidth: null,
14373				lastPercentToPxHeight: null,
14374				lastEmToPx: null,
14375				remToPx: null,
14376				vwToPx: null,
14377				vhToPx: null
14378			};
14379
14380			/* A container for all the ensuing tween data and metadata associated with this call. This container gets pushed to the page-wide
14381			 Velocity.State.calls array that is processed during animation ticking. */
14382			var call = [];
14383
14384			/************************
14385			 Element Processing
14386			 ************************/
14387
14388			/* Element processing consists of three parts -- data processing that cannot go stale and data processing that *can* go stale (i.e. third-party style modifications):
14389			 1) Pre-Queueing: Element-wide variables, including the element's data storage, are instantiated. Call options are prepared. If triggered, the Stop action is executed.
14390			 2) Queueing: The logic that runs once this call has reached its point of execution in the element's $.queue() stack. Most logic is placed here to avoid risking it becoming stale.
14391			 3) Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container.
14392			 `elementArrayIndex` allows passing index of the element in the original array to value functions.
14393			 If `elementsIndex` were used instead the index would be determined by the elements' per-element queue.
14394			 */
14395			function processElement(element, elementArrayIndex) {
14396
14397				/*************************
14398				 Part I: Pre-Queueing
14399				 *************************/
14400
14401				/***************************
14402				 Element-Wide Variables
14403				 ***************************/
14404
14405				var /* The runtime opts object is the extension of the current call's options and Velocity's page-wide option defaults. */
14406						opts = $.extend({}, Velocity.defaults, options),
14407						/* A container for the processed data associated with each property in the propertyMap.
14408						 (Each property in the map produces its own "tween".) */
14409						tweensContainer = {},
14410						elementUnitConversionData;
14411
14412				/******************
14413				 Element Init
14414				 ******************/
14415
14416				if (Data(element) === undefined) {
14417					Velocity.init(element);
14418				}
14419
14420				/******************
14421				 Option: Delay
14422				 ******************/
14423
14424				/* Since queue:false doesn't respect the item's existing queue, we avoid injecting its delay here (it's set later on). */
14425				/* Note: Velocity rolls its own delay function since jQuery doesn't have a utility alias for $.fn.delay()
14426				 (and thus requires jQuery element creation, which we avoid since its overhead includes DOM querying). */
14427				if (parseFloat(opts.delay) && opts.queue !== false) {
14428					$.queue(element, opts.queue, function(next, clearQueue) {
14429						if (clearQueue === true) {
14430							/* Do not continue with animation queueing. */
14431							return true;
14432						}
14433
14434						/* This is a flag used to indicate to the upcoming completeCall() function that this queue entry was initiated by Velocity. See completeCall() for further details. */
14435						Velocity.velocityQueueEntryFlag = true;
14436
14437						/* The ensuing queue item (which is assigned to the "next" argument that $.queue() automatically passes in) will be triggered after a setTimeout delay.
14438						 The setTimeout is stored so that it can be subjected to clearTimeout() if this animation is prematurely stopped via Velocity's "stop" command, and
14439						 delayBegin/delayTime is used to ensure we can "pause" and "resume" a tween that is still mid-delay. */
14440
14441						/* Temporarily store delayed elements to facilite access for global pause/resume */
14442						var callIndex = Velocity.State.delayedElements.count++;
14443						Velocity.State.delayedElements[callIndex] = element;
14444
14445						var delayComplete = (function(index) {
14446							return function() {
14447								/* Clear the temporary element */
14448								Velocity.State.delayedElements[index] = false;
14449
14450								/* Finally, issue the call */
14451								next();
14452							};
14453						})(callIndex);
14454
14455
14456						Data(element).delayBegin = (new Date()).getTime();
14457						Data(element).delay = parseFloat(opts.delay);
14458						Data(element).delayTimer = {
14459							setTimeout: setTimeout(next, parseFloat(opts.delay)),
14460							next: delayComplete
14461						};
14462					});
14463				}
14464
14465				/*********************
14466				 Option: Duration
14467				 *********************/
14468
14469				/* Support for jQuery's named durations. */
14470				switch (opts.duration.toString().toLowerCase()) {
14471					case "fast":
14472						opts.duration = 200;
14473						break;
14474
14475					case "normal":
14476						opts.duration = DURATION_DEFAULT;
14477						break;
14478
14479					case "slow":
14480						opts.duration = 600;
14481						break;
14482
14483					default:
14484						/* Remove the potential "ms" suffix and default to 1 if the user is attempting to set a duration of 0 (in order to produce an immediate style change). */
14485						opts.duration = parseFloat(opts.duration) || 1;
14486				}
14487
14488				/************************
14489				 Global Option: Mock
14490				 ************************/
14491
14492				if (Velocity.mock !== false) {
14493					/* In mock mode, all animations are forced to 1ms so that they occur immediately upon the next rAF tick.
14494					 Alternatively, a multiplier can be passed in to time remap all delays and durations. */
14495					if (Velocity.mock === true) {
14496						opts.duration = opts.delay = 1;
14497					} else {
14498						opts.duration *= parseFloat(Velocity.mock) || 1;
14499						opts.delay *= parseFloat(Velocity.mock) || 1;
14500					}
14501				}
14502
14503				/*******************
14504				 Option: Easing
14505				 *******************/
14506
14507				opts.easing = getEasing(opts.easing, opts.duration);
14508
14509				/**********************
14510				 Option: Callbacks
14511				 **********************/
14512
14513				/* Callbacks must functions. Otherwise, default to null. */
14514				if (opts.begin && !Type.isFunction(opts.begin)) {
14515					opts.begin = null;
14516				}
14517
14518				if (opts.progress && !Type.isFunction(opts.progress)) {
14519					opts.progress = null;
14520				}
14521
14522				if (opts.complete && !Type.isFunction(opts.complete)) {
14523					opts.complete = null;
14524				}
14525
14526				/*********************************
14527				 Option: Display & Visibility
14528				 *********************************/
14529
14530				/* Refer to Velocity's documentation (VelocityJS.org/#displayAndVisibility) for a description of the display and visibility options' behavior. */
14531				/* Note: We strictly check for undefined instead of falsiness because display accepts an empty string value. */
14532				if (opts.display !== undefined && opts.display !== null) {
14533					opts.display = opts.display.toString().toLowerCase();
14534
14535					/* Users can pass in a special "auto" value to instruct Velocity to set the element to its default display value. */
14536					if (opts.display === "auto") {
14537						opts.display = Velocity.CSS.Values.getDisplayType(element);
14538					}
14539				}
14540
14541				if (opts.visibility !== undefined && opts.visibility !== null) {
14542					opts.visibility = opts.visibility.toString().toLowerCase();
14543				}
14544
14545				/**********************
14546				 Option: mobileHA
14547				 **********************/
14548
14549				/* When set to true, and if this is a mobile device, mobileHA automatically enables hardware acceleration (via a null transform hack)
14550				 on animating elements. HA is removed from the element at the completion of its animation. */
14551				/* Note: Android Gingerbread doesn't support HA. If a null transform hack (mobileHA) is in fact set, it will prevent other tranform subproperties from taking effect. */
14552				/* Note: You can read more about the use of mobileHA in Velocity's documentation: VelocityJS.org/#mobileHA. */
14553				opts.mobileHA = (opts.mobileHA && Velocity.State.isMobile && !Velocity.State.isGingerbread);
14554
14555				/***********************
14556				 Part II: Queueing
14557				 ***********************/
14558
14559				/* When a set of elements is targeted by a Velocity call, the set is broken up and each element has the current Velocity call individually queued onto it.
14560				 In this way, each element's existing queue is respected; some elements may already be animating and accordingly should not have this current Velocity call triggered immediately. */
14561				/* In each queue, tween data is processed for each animating property then pushed onto the call-wide calls array. When the last element in the set has had its tweens processed,
14562				 the call array is pushed to Velocity.State.calls for live processing by the requestAnimationFrame tick. */
14563				function buildQueue(next) {
14564					var data, lastTweensContainer;
14565
14566					/*******************
14567					 Option: Begin
14568					 *******************/
14569
14570					/* The begin callback is fired once per call -- not once per elemenet -- and is passed the full raw DOM element set as both its context and its first argument. */
14571					if (opts.begin && elementsIndex === 0) {
14572						/* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */
14573						try {
14574							opts.begin.call(elements, elements);
14575						} catch (error) {
14576							setTimeout(function() {
14577								throw error;
14578							}, 1);
14579						}
14580					}
14581
14582					/*****************************************
14583					 Tween Data Construction (for Scroll)
14584					 *****************************************/
14585
14586					/* Note: In order to be subjected to chaining and animation options, scroll's tweening is routed through Velocity as if it were a standard CSS property animation. */
14587					if (action === "scroll") {
14588						/* The scroll action uniquely takes an optional "offset" option -- specified in pixels -- that offsets the targeted scroll position. */
14589						var scrollDirection = (/^x$/i.test(opts.axis) ? "Left" : "Top"),
14590								scrollOffset = parseFloat(opts.offset) || 0,
14591								scrollPositionCurrent,
14592								scrollPositionCurrentAlternate,
14593								scrollPositionEnd;
14594
14595						/* Scroll also uniquely takes an optional "container" option, which indicates the parent element that should be scrolled --
14596						 as opposed to the browser window itself. This is useful for scrolling toward an element that's inside an overflowing parent element. */
14597						if (opts.container) {
14598							/* Ensure that either a jQuery object or a raw DOM element was passed in. */
14599							if (Type.isWrapped(opts.container) || Type.isNode(opts.container)) {
14600								/* Extract the raw DOM element from the jQuery wrapper. */
14601								opts.container = opts.container[0] || opts.container;
14602								/* Note: Unlike other properties in Velocity, the browser's scroll position is never cached since it so frequently changes
14603								 (due to the user's natural interaction with the page). */
14604								scrollPositionCurrent = opts.container["scroll" + scrollDirection]; /* GET */
14605
14606								/* $.position() values are relative to the container's currently viewable area (without taking into account the container's true dimensions
14607								 -- say, for example, if the container was not overflowing). Thus, the scroll end value is the sum of the child element's position *and*
14608								 the scroll container's current scroll position. */
14609								scrollPositionEnd = (scrollPositionCurrent + $(element).position()[scrollDirection.toLowerCase()]) + scrollOffset; /* GET */
14610								/* If a value other than a jQuery object or a raw DOM element was passed in, default to null so that this option is ignored. */
14611							} else {
14612								opts.container = null;
14613							}
14614						} else {
14615							/* If the window itself is being scrolled -- not a containing element -- perform a live scroll position lookup using
14616							 the appropriate cached property names (which differ based on browser type). */
14617							scrollPositionCurrent = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + scrollDirection]]; /* GET */
14618							/* When scrolling the browser window, cache the alternate axis's current value since window.scrollTo() doesn't let us change only one value at a time. */
14619							scrollPositionCurrentAlternate = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + (scrollDirection === "Left" ? "Top" : "Left")]]; /* GET */
14620
14621							/* Unlike $.position(), $.offset() values are relative to the browser window's true dimensions -- not merely its currently viewable area --
14622							 and therefore end values do not need to be compounded onto current values. */
14623							scrollPositionEnd = $(element).offset()[scrollDirection.toLowerCase()] + scrollOffset; /* GET */
14624						}
14625
14626						/* Since there's only one format that scroll's associated tweensContainer can take, we create it manually. */
14627						tweensContainer = {
14628							scroll: {
14629								rootPropertyValue: false,
14630								startValue: scrollPositionCurrent,
14631								currentValue: scrollPositionCurrent,
14632								endValue: scrollPositionEnd,
14633								unitType: "",
14634								easing: opts.easing,
14635								scrollData: {
14636									container: opts.container,
14637									direction: scrollDirection,
14638									alternateValue: scrollPositionCurrentAlternate
14639								}
14640							},
14641							element: element
14642						};
14643
14644						if (Velocity.debug) {
14645							console.log("tweensContainer (scroll): ", tweensContainer.scroll, element);
14646						}
14647
14648						/******************************************
14649						 Tween Data Construction (for Reverse)
14650						 ******************************************/
14651
14652						/* Reverse acts like a "start" action in that a property map is animated toward. The only difference is
14653						 that the property map used for reverse is the inverse of the map used in the previous call. Thus, we manipulate
14654						 the previous call to construct our new map: use the previous map's end values as our new map's start values. Copy over all other data. */
14655						/* Note: Reverse can be directly called via the "reverse" parameter, or it can be indirectly triggered via the loop option. (Loops are composed of multiple reverses.) */
14656						/* Note: Reverse calls do not need to be consecutively chained onto a currently-animating element in order to operate on cached values;
14657						 there is no harm to reverse being called on a potentially stale data cache since reverse's behavior is simply defined
14658						 as reverting to the element's values as they were prior to the previous *Velocity* call. */
14659					} else if (action === "reverse") {
14660						data = Data(element);
14661
14662						/* Abort if there is no prior animation data to reverse to. */
14663						if (!data) {
14664							return;
14665						}
14666
14667						if (!data.tweensContainer) {
14668							/* Dequeue the element so that this queue entry releases itself immediately, allowing subsequent queue entries to run. */
14669							$.dequeue(element, opts.queue);
14670
14671							return;
14672						} else {
14673							/*********************
14674							 Options Parsing
14675							 *********************/
14676
14677							/* If the element was hidden via the display option in the previous call,
14678							 revert display to "auto" prior to reversal so that the element is visible again. */
14679							if (data.opts.display === "none") {
14680								data.opts.display = "auto";
14681							}
14682
14683							if (data.opts.visibility === "hidden") {
14684								data.opts.visibility = "visible";
14685							}
14686
14687							/* If the loop option was set in the previous call, disable it so that "reverse" calls aren't recursively generated.
14688							 Further, remove the previous call's callback options; typically, users do not want these to be refired. */
14689							data.opts.loop = false;
14690							data.opts.begin = null;
14691							data.opts.complete = null;
14692
14693							/* Since we're extending an opts object that has already been extended with the defaults options object,
14694							 we remove non-explicitly-defined properties that are auto-assigned values. */
14695							if (!options.easing) {
14696								delete opts.easing;
14697							}
14698
14699							if (!options.duration) {
14700								delete opts.duration;
14701							}
14702
14703							/* The opts object used for reversal is an extension of the options object optionally passed into this
14704							 reverse call plus the options used in the previous Velocity call. */
14705							opts = $.extend({}, data.opts, opts);
14706
14707							/*************************************
14708							 Tweens Container Reconstruction
14709							 *************************************/
14710
14711							/* Create a deepy copy (indicated via the true flag) of the previous call's tweensContainer. */
14712							lastTweensContainer = $.extend(true, {}, data ? data.tweensContainer : null);
14713
14714							/* Manipulate the previous tweensContainer by replacing its end values and currentValues with its start values. */
14715							for (var lastTween in lastTweensContainer) {
14716								/* In addition to tween data, tweensContainers contain an element property that we ignore here. */
14717								if (lastTweensContainer.hasOwnProperty(lastTween) && lastTween !== "element") {
14718									var lastStartValue = lastTweensContainer[lastTween].startValue;
14719
14720									lastTweensContainer[lastTween].startValue = lastTweensContainer[lastTween].currentValue = lastTweensContainer[lastTween].endValue;
14721									lastTweensContainer[lastTween].endValue = lastStartValue;
14722
14723									/* Easing is the only option that embeds into the individual tween data (since it can be defined on a per-property basis).
14724									 Accordingly, every property's easing value must be updated when an options object is passed in with a reverse call.
14725									 The side effect of this extensibility is that all per-property easing values are forcefully reset to the new value. */
14726									if (!Type.isEmptyObject(options)) {
14727										lastTweensContainer[lastTween].easing = opts.easing;
14728									}
14729
14730									if (Velocity.debug) {
14731										console.log("reverse tweensContainer (" + lastTween + "): " + JSON.stringify(lastTweensContainer[lastTween]), element);
14732									}
14733								}
14734							}
14735
14736							tweensContainer = lastTweensContainer;
14737						}
14738
14739						/*****************************************
14740						 Tween Data Construction (for Start)
14741						 *****************************************/
14742
14743					} else if (action === "start") {
14744
14745						/*************************
14746						 Value Transferring
14747						 *************************/
14748
14749						/* If this queue entry follows a previous Velocity-initiated queue entry *and* if this entry was created
14750						 while the element was in the process of being animated by Velocity, then this current call is safe to use
14751						 the end values from the prior call as its start values. Velocity attempts to perform this value transfer
14752						 process whenever possible in order to avoid requerying the DOM. */
14753						/* If values aren't transferred from a prior call and start values were not forcefed by the user (more on this below),
14754						 then the DOM is queried for the element's current values as a last resort. */
14755						/* Note: Conversely, animation reversal (and looping) *always* perform inter-call value transfers; they never requery the DOM. */
14756
14757						data = Data(element);
14758
14759						/* The per-element isAnimating flag is used to indicate whether it's safe (i.e. the data isn't stale)
14760						 to transfer over end values to use as start values. If it's set to true and there is a previous
14761						 Velocity call to pull values from, do so. */
14762						if (data && data.tweensContainer && data.isAnimating === true) {
14763							lastTweensContainer = data.tweensContainer;
14764						}
14765
14766						/***************************
14767						 Tween Data Calculation
14768						 ***************************/
14769
14770						/* This function parses property data and defaults endValue, easing, and startValue as appropriate. */
14771						/* Property map values can either take the form of 1) a single value representing the end value,
14772						 or 2) an array in the form of [ endValue, [, easing] [, startValue] ].
14773						 The optional third parameter is a forcefed startValue to be used instead of querying the DOM for
14774						 the element's current value. Read Velocity's docmentation to learn more about forcefeeding: VelocityJS.org/#forcefeeding */
14775						var parsePropertyValue = function(valueData, skipResolvingEasing) {
14776							var endValue, easing, startValue;
14777
14778							/* If we have a function as the main argument then resolve it first, in case it returns an array that needs to be split */
14779							if (Type.isFunction(valueData)) {
14780								valueData = valueData.call(element, elementArrayIndex, elementsLength);
14781							}
14782
14783							/* Handle the array format, which can be structured as one of three potential overloads:
14784							 A) [ endValue, easing, startValue ], B) [ endValue, easing ], or C) [ endValue, startValue ] */
14785							if (Type.isArray(valueData)) {
14786								/* endValue is always the first item in the array. Don't bother validating endValue's value now
14787								 since the ensuing property cycling logic does that. */
14788								endValue = valueData[0];
14789
14790								/* Two-item array format: If the second item is a number, function, or hex string, treat it as a
14791								 start value since easings can only be non-hex strings or arrays. */
14792								if ((!Type.isArray(valueData[1]) && /^[\d-]/.test(valueData[1])) || Type.isFunction(valueData[1]) || CSS.RegEx.isHex.test(valueData[1])) {
14793									startValue = valueData[1];
14794									/* Two or three-item array: If the second item is a non-hex string easing name or an array, treat it as an easing. */
14795								} else if ((Type.isString(valueData[1]) && !CSS.RegEx.isHex.test(valueData[1]) && Velocity.Easings[valueData[1]]) || Type.isArray(valueData[1])) {
14796									easing = skipResolvingEasing ? valueData[1] : getEasing(valueData[1], opts.duration);
14797
14798									/* Don't bother validating startValue's value now since the ensuing property cycling logic inherently does that. */
14799									startValue = valueData[2];
14800								} else {
14801									startValue = valueData[1] || valueData[2];
14802								}
14803								/* Handle the single-value format. */
14804							} else {
14805								endValue = valueData;
14806							}
14807
14808							/* Default to the call's easing if a per-property easing type was not defined. */
14809							if (!skipResolvingEasing) {
14810								easing = easing || opts.easing;
14811							}
14812
14813							/* If functions were passed in as values, pass the function the current element as its context,
14814							 plus the element's index and the element set's size as arguments. Then, assign the returned value. */
14815							if (Type.isFunction(endValue)) {
14816								endValue = endValue.call(element, elementArrayIndex, elementsLength);
14817							}
14818
14819							if (Type.isFunction(startValue)) {
14820								startValue = startValue.call(element, elementArrayIndex, elementsLength);
14821							}
14822
14823							/* Allow startValue to be left as undefined to indicate to the ensuing code that its value was not forcefed. */
14824							return [endValue || 0, easing, startValue];
14825						};
14826
14827						var fixPropertyValue = function(property, valueData) {
14828							/* In case this property is a hook, there are circumstances where we will intend to work on the hook's root property and not the hooked subproperty. */
14829							var rootProperty = CSS.Hooks.getRoot(property),
14830									rootPropertyValue = false,
14831									/* Parse out endValue, easing, and startValue from the property's data. */
14832									endValue = valueData[0],
14833									easing = valueData[1],
14834									startValue = valueData[2],
14835									pattern;
14836
14837							/**************************
14838							 Start Value Sourcing
14839							 **************************/
14840
14841							/* Other than for the dummy tween property, properties that are not supported by the browser (and do not have an associated normalization) will
14842							 inherently produce no style changes when set, so they are skipped in order to decrease animation tick overhead.
14843							 Property support is determined via prefixCheck(), which returns a false flag when no supported is detected. */
14844							/* Note: Since SVG elements have some of their properties directly applied as HTML attributes,
14845							 there is no way to check for their explicit browser support, and so we skip skip this check for them. */
14846							if ((!data || !data.isSVG) && rootProperty !== "tween" && CSS.Names.prefixCheck(rootProperty)[1] === false && CSS.Normalizations.registered[rootProperty] === undefined) {
14847								if (Velocity.debug) {
14848									console.log("Skipping [" + rootProperty + "] due to a lack of browser support.");
14849								}
14850								return;
14851							}
14852
14853							/* If the display option is being set to a non-"none" (e.g. "block") and opacity (filter on IE<=8) is being
14854							 animated to an endValue of non-zero, the user's intention is to fade in from invisible, thus we forcefeed opacity
14855							 a startValue of 0 if its startValue hasn't already been sourced by value transferring or prior forcefeeding. */
14856							if (((opts.display !== undefined && opts.display !== null && opts.display !== "none") || (opts.visibility !== undefined && opts.visibility !== "hidden")) && /opacity|filter/.test(property) && !startValue && endValue !== 0) {
14857								startValue = 0;
14858							}
14859
14860							/* If values have been transferred from the previous Velocity call, extract the endValue and rootPropertyValue
14861							 for all of the current call's properties that were *also* animated in the previous call. */
14862							/* Note: Value transferring can optionally be disabled by the user via the _cacheValues option. */
14863							if (opts._cacheValues && lastTweensContainer && lastTweensContainer[property]) {
14864								if (startValue === undefined) {
14865									startValue = lastTweensContainer[property].endValue + lastTweensContainer[property].unitType;
14866								}
14867
14868								/* The previous call's rootPropertyValue is extracted from the element's data cache since that's the
14869								 instance of rootPropertyValue that gets freshly updated by the tweening process, whereas the rootPropertyValue
14870								 attached to the incoming lastTweensContainer is equal to the root property's value prior to any tweening. */
14871								rootPropertyValue = data.rootPropertyValueCache[rootProperty];
14872								/* If values were not transferred from a previous Velocity call, query the DOM as needed. */
14873							} else {
14874								/* Handle hooked properties. */
14875								if (CSS.Hooks.registered[property]) {
14876									if (startValue === undefined) {
14877										rootPropertyValue = CSS.getPropertyValue(element, rootProperty); /* GET */
14878										/* Note: The following getPropertyValue() call does not actually trigger a DOM query;
14879										 getPropertyValue() will extract the hook from rootPropertyValue. */
14880										startValue = CSS.getPropertyValue(element, property, rootPropertyValue);
14881										/* If startValue is already defined via forcefeeding, do not query the DOM for the root property's value;
14882										 just grab rootProperty's zero-value template from CSS.Hooks. This overwrites the element's actual
14883										 root property value (if one is set), but this is acceptable since the primary reason users forcefeed is
14884										 to avoid DOM queries, and thus we likewise avoid querying the DOM for the root property's value. */
14885									} else {
14886										/* Grab this hook's zero-value template, e.g. "0px 0px 0px black". */
14887										rootPropertyValue = CSS.Hooks.templates[rootProperty][1];
14888									}
14889									/* Handle non-hooked properties that haven't already been defined via forcefeeding. */
14890								} else if (startValue === undefined) {
14891									startValue = CSS.getPropertyValue(element, property); /* GET */
14892								}
14893							}
14894
14895							/**************************
14896							 Value Data Extraction
14897							 **************************/
14898
14899							var separatedValue,
14900									endValueUnitType,
14901									startValueUnitType,
14902									operator = false;
14903
14904							/* Separates a property value into its numeric value and its unit type. */
14905							var separateValue = function(property, value) {
14906								var unitType,
14907										numericValue;
14908
14909								numericValue = (value || "0")
14910										.toString()
14911										.toLowerCase()
14912										/* Match the unit type at the end of the value. */
14913										.replace(/[%A-z]+$/, function(match) {
14914											/* Grab the unit type. */
14915											unitType = match;
14916
14917											/* Strip the unit type off of value. */
14918											return "";
14919										});
14920
14921								/* If no unit type was supplied, assign one that is appropriate for this property (e.g. "deg" for rotateZ or "px" for width). */
14922								if (!unitType) {
14923									unitType = CSS.Values.getUnitType(property);
14924								}
14925
14926								return [numericValue, unitType];
14927							};
14928
14929							if (startValue !== endValue && Type.isString(startValue) && Type.isString(endValue)) {
14930								pattern = "";
14931								var iStart = 0, // index in startValue
14932										iEnd = 0, // index in endValue
14933										aStart = [], // array of startValue numbers
14934										aEnd = [], // array of endValue numbers
14935										inCalc = 0, // Keep track of being inside a "calc()" so we don't duplicate it
14936										inRGB = 0, // Keep track of being inside an RGB as we can't use fractional values
14937										inRGBA = 0; // Keep track of being inside an RGBA as we must pass fractional for the alpha channel
14938
14939								startValue = CSS.Hooks.fixColors(startValue);
14940								endValue = CSS.Hooks.fixColors(endValue);
14941								while (iStart < startValue.length && iEnd < endValue.length) {
14942									var cStart = startValue[iStart],
14943											cEnd = endValue[iEnd];
14944
14945									if (/[\d\.-]/.test(cStart) && /[\d\.-]/.test(cEnd)) {
14946										var tStart = cStart, // temporary character buffer
14947												tEnd = cEnd, // temporary character buffer
14948												dotStart = ".", // Make sure we can only ever match a single dot in a decimal
14949												dotEnd = "."; // Make sure we can only ever match a single dot in a decimal
14950
14951										while (++iStart < startValue.length) {
14952											cStart = startValue[iStart];
14953											if (cStart === dotStart) {
14954												dotStart = ".."; // Can never match two characters
14955											} else if (!/\d/.test(cStart)) {
14956												break;
14957											}
14958											tStart += cStart;
14959										}
14960										while (++iEnd < endValue.length) {
14961											cEnd = endValue[iEnd];
14962											if (cEnd === dotEnd) {
14963												dotEnd = ".."; // Can never match two characters
14964											} else if (!/\d/.test(cEnd)) {
14965												break;
14966											}
14967											tEnd += cEnd;
14968										}
14969										var uStart = CSS.Hooks.getUnit(startValue, iStart), // temporary unit type
14970												uEnd = CSS.Hooks.getUnit(endValue, iEnd); // temporary unit type
14971
14972										iStart += uStart.length;
14973										iEnd += uEnd.length;
14974										if (uStart === uEnd) {
14975											// Same units
14976											if (tStart === tEnd) {
14977												// Same numbers, so just copy over
14978												pattern += tStart + uStart;
14979											} else {
14980												// Different numbers, so store them
14981												pattern += "{" + aStart.length + (inRGB ? "!" : "") + "}" + uStart;
14982												aStart.push(parseFloat(tStart));
14983												aEnd.push(parseFloat(tEnd));
14984											}
14985										} else {
14986											// Different units, so put into a "calc(from + to)" and animate each side to/from zero
14987											var nStart = parseFloat(tStart),
14988													nEnd = parseFloat(tEnd);
14989
14990											pattern += (inCalc < 5 ? "calc" : "") + "("
14991													+ (nStart ? "{" + aStart.length + (inRGB ? "!" : "") + "}" : "0") + uStart
14992													+ " + "
14993													+ (nEnd ? "{" + (aStart.length + (nStart ? 1 : 0)) + (inRGB ? "!" : "") + "}" : "0") + uEnd
14994													+ ")";
14995											if (nStart) {
14996												aStart.push(nStart);
14997												aEnd.push(0);
14998											}
14999											if (nEnd) {
15000												aStart.push(0);
15001												aEnd.push(nEnd);
15002											}
15003										}
15004									} else if (cStart === cEnd) {
15005										pattern += cStart;
15006										iStart++;
15007										iEnd++;
15008										// Keep track of being inside a calc()
15009										if (inCalc === 0 && cStart === "c"
15010												|| inCalc === 1 && cStart === "a"
15011												|| inCalc === 2 && cStart === "l"
15012												|| inCalc === 3 && cStart === "c"
15013												|| inCalc >= 4 && cStart === "("
15014												) {
15015											inCalc++;
15016										} else if ((inCalc && inCalc < 5)
15017												|| inCalc >= 4 && cStart === ")" && --inCalc < 5) {
15018											inCalc = 0;
15019										}
15020										// Keep track of being inside an rgb() / rgba()
15021										if (inRGB === 0 && cStart === "r"
15022												|| inRGB === 1 && cStart === "g"
15023												|| inRGB === 2 && cStart === "b"
15024												|| inRGB === 3 && cStart === "a"
15025												|| inRGB >= 3 && cStart === "("
15026												) {
15027											if (inRGB === 3 && cStart === "a") {
15028												inRGBA = 1;
15029											}
15030											inRGB++;
15031										} else if (inRGBA && cStart === ",") {
15032											if (++inRGBA > 3) {
15033												inRGB = inRGBA = 0;
15034											}
15035										} else if ((inRGBA && inRGB < (inRGBA ? 5 : 4))
15036												|| inRGB >= (inRGBA ? 4 : 3) && cStart === ")" && --inRGB < (inRGBA ? 5 : 4)) {
15037											inRGB = inRGBA = 0;
15038										}
15039									} else {
15040										inCalc = 0;
15041										// TODO: changing units, fixing colours
15042										break;
15043									}
15044								}
15045								if (iStart !== startValue.length || iEnd !== endValue.length) {
15046									if (Velocity.debug) {
15047										console.error("Trying to pattern match mis-matched strings [\"" + endValue + "\", \"" + startValue + "\"]");
15048									}
15049									pattern = undefined;
15050								}
15051								if (pattern) {
15052									if (aStart.length) {
15053										if (Velocity.debug) {
15054											console.log("Pattern found \"" + pattern + "\" -> ", aStart, aEnd, "[" + startValue + "," + endValue + "]");
15055										}
15056										startValue = aStart;
15057										endValue = aEnd;
15058										endValueUnitType = startValueUnitType = "";
15059									} else {
15060										pattern = undefined;
15061									}
15062								}
15063							}
15064
15065							if (!pattern) {
15066								/* Separate startValue. */
15067								separatedValue = separateValue(property, startValue);
15068								startValue = separatedValue[0];
15069								startValueUnitType = separatedValue[1];
15070
15071								/* Separate endValue, and extract a value operator (e.g. "+=", "-=") if one exists. */
15072								separatedValue = separateValue(property, endValue);
15073								endValue = separatedValue[0].replace(/^([+-\/*])=/, function(match, subMatch) {
15074									operator = subMatch;
15075
15076									/* Strip the operator off of the value. */
15077									return "";
15078								});
15079								endValueUnitType = separatedValue[1];
15080
15081								/* Parse float values from endValue and startValue. Default to 0 if NaN is returned. */
15082								startValue = parseFloat(startValue) || 0;
15083								endValue = parseFloat(endValue) || 0;
15084
15085								/***************************************
15086								 Property-Specific Value Conversion
15087								 ***************************************/
15088
15089								/* Custom support for properties that don't actually accept the % unit type, but where pollyfilling is trivial and relatively foolproof. */
15090								if (endValueUnitType === "%") {
15091									/* A %-value fontSize/lineHeight is relative to the parent's fontSize (as opposed to the parent's dimensions),
15092									 which is identical to the em unit's behavior, so we piggyback off of that. */
15093									if (/^(fontSize|lineHeight)$/.test(property)) {
15094										/* Convert % into an em decimal value. */
15095										endValue = endValue / 100;
15096										endValueUnitType = "em";
15097										/* For scaleX and scaleY, convert the value into its decimal format and strip off the unit type. */
15098									} else if (/^scale/.test(property)) {
15099										endValue = endValue / 100;
15100										endValueUnitType = "";
15101										/* For RGB components, take the defined percentage of 255 and strip off the unit type. */
15102									} else if (/(Red|Green|Blue)$/i.test(property)) {
15103										endValue = (endValue / 100) * 255;
15104										endValueUnitType = "";
15105									}
15106								}
15107							}
15108
15109							/***************************
15110							 Unit Ratio Calculation
15111							 ***************************/
15112
15113							/* When queried, the browser returns (most) CSS property values in pixels. Therefore, if an endValue with a unit type of
15114							 %, em, or rem is animated toward, startValue must be converted from pixels into the same unit type as endValue in order
15115							 for value manipulation logic (increment/decrement) to proceed. Further, if the startValue was forcefed or transferred
15116							 from a previous call, startValue may also not be in pixels. Unit conversion logic therefore consists of two steps:
15117							 1) Calculating the ratio of %/em/rem/vh/vw relative to pixels
15118							 2) Converting startValue into the same unit of measurement as endValue based on these ratios. */
15119							/* Unit conversion ratios are calculated by inserting a sibling node next to the target node, copying over its position property,
15120							 setting values with the target unit type then comparing the returned pixel value. */
15121							/* Note: Even if only one of these unit types is being animated, all unit ratios are calculated at once since the overhead
15122							 of batching the SETs and GETs together upfront outweights the potential overhead
15123							 of layout thrashing caused by re-querying for uncalculated ratios for subsequently-processed properties. */
15124							/* Todo: Shift this logic into the calls' first tick instance so that it's synced with RAF. */
15125							var calculateUnitRatios = function() {
15126
15127								/************************
15128								 Same Ratio Checks
15129								 ************************/
15130
15131								/* The properties below are used to determine whether the element differs sufficiently from this call's
15132								 previously iterated element to also differ in its unit conversion ratios. If the properties match up with those
15133								 of the prior element, the prior element's conversion ratios are used. Like most optimizations in Velocity,
15134								 this is done to minimize DOM querying. */
15135								var sameRatioIndicators = {
15136									myParent: element.parentNode || document.body, /* GET */
15137									position: CSS.getPropertyValue(element, "position"), /* GET */
15138									fontSize: CSS.getPropertyValue(element, "fontSize") /* GET */
15139								},
15140										/* Determine if the same % ratio can be used. % is based on the element's position value and its parent's width and height dimensions. */
15141										samePercentRatio = ((sameRatioIndicators.position === callUnitConversionData.lastPosition) && (sameRatioIndicators.myParent === callUnitConversionData.lastParent)),
15142										/* Determine if the same em ratio can be used. em is relative to the element's fontSize. */
15143										sameEmRatio = (sameRatioIndicators.fontSize === callUnitConversionData.lastFontSize);
15144
15145								/* Store these ratio indicators call-wide for the next element to compare against. */
15146								callUnitConversionData.lastParent = sameRatioIndicators.myParent;
15147								callUnitConversionData.lastPosition = sameRatioIndicators.position;
15148								callUnitConversionData.lastFontSize = sameRatioIndicators.fontSize;
15149
15150								/***************************
15151								 Element-Specific Units
15152								 ***************************/
15153
15154								/* Note: IE8 rounds to the nearest pixel when returning CSS values, thus we perform conversions using a measurement
15155								 of 100 (instead of 1) to give our ratios a precision of at least 2 decimal values. */
15156								var measurement = 100,
15157										unitRatios = {};
15158
15159								if (!sameEmRatio || !samePercentRatio) {
15160									var dummy = data && data.isSVG ? document.createElementNS("http://www.w3.org/2000/svg", "rect") : document.createElement("div");
15161
15162									Velocity.init(dummy);
15163									sameRatioIndicators.myParent.appendChild(dummy);
15164
15165									/* To accurately and consistently calculate conversion ratios, the element's cascaded overflow and box-sizing are stripped.
15166									 Similarly, since width/height can be artificially constrained by their min-/max- equivalents, these are controlled for as well. */
15167									/* Note: Overflow must be also be controlled for per-axis since the overflow property overwrites its per-axis values. */
15168									$.each(["overflow", "overflowX", "overflowY"], function(i, property) {
15169										Velocity.CSS.setPropertyValue(dummy, property, "hidden");
15170									});
15171									Velocity.CSS.setPropertyValue(dummy, "position", sameRatioIndicators.position);
15172									Velocity.CSS.setPropertyValue(dummy, "fontSize", sameRatioIndicators.fontSize);
15173									Velocity.CSS.setPropertyValue(dummy, "boxSizing", "content-box");
15174
15175									/* width and height act as our proxy properties for measuring the horizontal and vertical % ratios. */
15176									$.each(["minWidth", "maxWidth", "width", "minHeight", "maxHeight", "height"], function(i, property) {
15177										Velocity.CSS.setPropertyValue(dummy, property, measurement + "%");
15178									});
15179									/* paddingLeft arbitrarily acts as our proxy property for the em ratio. */
15180									Velocity.CSS.setPropertyValue(dummy, "paddingLeft", measurement + "em");
15181
15182									/* Divide the returned value by the measurement to get the ratio between 1% and 1px. Default to 1 since working with 0 can produce Infinite. */
15183									unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth = (parseFloat(CSS.getPropertyValue(dummy, "width", null, true)) || 1) / measurement; /* GET */
15184									unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight = (parseFloat(CSS.getPropertyValue(dummy, "height", null, true)) || 1) / measurement; /* GET */
15185									unitRatios.emToPx = callUnitConversionData.lastEmToPx = (parseFloat(CSS.getPropertyValue(dummy, "paddingLeft")) || 1) / measurement; /* GET */
15186
15187									sameRatioIndicators.myParent.removeChild(dummy);
15188								} else {
15189									unitRatios.emToPx = callUnitConversionData.lastEmToPx;
15190									unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth;
15191									unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight;
15192								}
15193
15194								/***************************
15195								 Element-Agnostic Units
15196								 ***************************/
15197
15198								/* Whereas % and em ratios are determined on a per-element basis, the rem unit only needs to be checked
15199								 once per call since it's exclusively dependant upon document.body's fontSize. If this is the first time
15200								 that calculateUnitRatios() is being run during this call, remToPx will still be set to its default value of null,
15201								 so we calculate it now. */
15202								if (callUnitConversionData.remToPx === null) {
15203									/* Default to browsers' default fontSize of 16px in the case of 0. */
15204									callUnitConversionData.remToPx = parseFloat(CSS.getPropertyValue(document.body, "fontSize")) || 16; /* GET */
15205								}
15206
15207								/* Similarly, viewport units are %-relative to the window's inner dimensions. */
15208								if (callUnitConversionData.vwToPx === null) {
15209									callUnitConversionData.vwToPx = parseFloat(window.innerWidth) / 100; /* GET */
15210									callUnitConversionData.vhToPx = parseFloat(window.innerHeight) / 100; /* GET */
15211								}
15212
15213								unitRatios.remToPx = callUnitConversionData.remToPx;
15214								unitRatios.vwToPx = callUnitConversionData.vwToPx;
15215								unitRatios.vhToPx = callUnitConversionData.vhToPx;
15216
15217								if (Velocity.debug >= 1) {
15218									console.log("Unit ratios: " + JSON.stringify(unitRatios), element);
15219								}
15220								return unitRatios;
15221							};
15222
15223							/********************
15224							 Unit Conversion
15225							 ********************/
15226
15227							/* The * and / operators, which are not passed in with an associated unit, inherently use startValue's unit. Skip value and unit conversion. */
15228							if (/[\/*]/.test(operator)) {
15229								endValueUnitType = startValueUnitType;
15230								/* If startValue and endValue differ in unit type, convert startValue into the same unit type as endValue so that if endValueUnitType
15231								 is a relative unit (%, em, rem), the values set during tweening will continue to be accurately relative even if the metrics they depend
15232								 on are dynamically changing during the course of the animation. Conversely, if we always normalized into px and used px for setting values, the px ratio
15233								 would become stale if the original unit being animated toward was relative and the underlying metrics change during the animation. */
15234								/* Since 0 is 0 in any unit type, no conversion is necessary when startValue is 0 -- we just start at 0 with endValueUnitType. */
15235							} else if ((startValueUnitType !== endValueUnitType) && startValue !== 0) {
15236								/* Unit conversion is also skipped when endValue is 0, but *startValueUnitType* must be used for tween values to remain accurate. */
15237								/* Note: Skipping unit conversion here means that if endValueUnitType was originally a relative unit, the animation won't relatively
15238								 match the underlying metrics if they change, but this is acceptable since we're animating toward invisibility instead of toward visibility,
15239								 which remains past the point of the animation's completion. */
15240								if (endValue === 0) {
15241									endValueUnitType = startValueUnitType;
15242								} else {
15243									/* By this point, we cannot avoid unit conversion (it's undesirable since it causes layout thrashing).
15244									 If we haven't already, we trigger calculateUnitRatios(), which runs once per element per call. */
15245									elementUnitConversionData = elementUnitConversionData || calculateUnitRatios();
15246
15247									/* The following RegEx matches CSS properties that have their % values measured relative to the x-axis. */
15248									/* Note: W3C spec mandates that all of margin and padding's properties (even top and bottom) are %-relative to the *width* of the parent element. */
15249									var axis = (/margin|padding|left|right|width|text|word|letter/i.test(property) || /X$/.test(property) || property === "x") ? "x" : "y";
15250
15251									/* In order to avoid generating n^2 bespoke conversion functions, unit conversion is a two-step process:
15252									 1) Convert startValue into pixels. 2) Convert this new pixel value into endValue's unit type. */
15253									switch (startValueUnitType) {
15254										case "%":
15255											/* Note: translateX and translateY are the only properties that are %-relative to an element's own dimensions -- not its parent's dimensions.
15256											 Velocity does not include a special conversion process to account for this behavior. Therefore, animating translateX/Y from a % value
15257											 to a non-% value will produce an incorrect start value. Fortunately, this sort of cross-unit conversion is rarely done by users in practice. */
15258											startValue *= (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight);
15259											break;
15260
15261										case "px":
15262											/* px acts as our midpoint in the unit conversion process; do nothing. */
15263											break;
15264
15265										default:
15266											startValue *= elementUnitConversionData[startValueUnitType + "ToPx"];
15267									}
15268
15269									/* Invert the px ratios to convert into to the target unit. */
15270									switch (endValueUnitType) {
15271										case "%":
15272											startValue *= 1 / (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight);
15273											break;
15274
15275										case "px":
15276											/* startValue is already in px, do nothing; we're done. */
15277											break;
15278
15279										default:
15280											startValue *= 1 / elementUnitConversionData[endValueUnitType + "ToPx"];
15281									}
15282								}
15283							}
15284
15285							/*********************
15286							 Relative Values
15287							 *********************/
15288
15289							/* Operator logic must be performed last since it requires unit-normalized start and end values. */
15290							/* Note: Relative *percent values* do not behave how most people think; while one would expect "+=50%"
15291							 to increase the property 1.5x its current value, it in fact increases the percent units in absolute terms:
15292							 50 points is added on top of the current % value. */
15293							switch (operator) {
15294								case "+":
15295									endValue = startValue + endValue;
15296									break;
15297
15298								case "-":
15299									endValue = startValue - endValue;
15300									break;
15301
15302								case "*":
15303									endValue = startValue * endValue;
15304									break;
15305
15306								case "/":
15307									endValue = startValue / endValue;
15308									break;
15309							}
15310
15311							/**************************
15312							 tweensContainer Push
15313							 **************************/
15314
15315							/* Construct the per-property tween object, and push it to the element's tweensContainer. */
15316							tweensContainer[property] = {
15317								rootPropertyValue: rootPropertyValue,
15318								startValue: startValue,
15319								currentValue: startValue,
15320								endValue: endValue,
15321								unitType: endValueUnitType,
15322								easing: easing
15323							};
15324							if (pattern) {
15325								tweensContainer[property].pattern = pattern;
15326							}
15327
15328							if (Velocity.debug) {
15329								console.log("tweensContainer (" + property + "): " + JSON.stringify(tweensContainer[property]), element);
15330							}
15331						};
15332
15333						/* Create a tween out of each property, and append its associated data to tweensContainer. */
15334						for (var property in propertiesMap) {
15335
15336							if (!propertiesMap.hasOwnProperty(property)) {
15337								continue;
15338							}
15339							/* The original property name's format must be used for the parsePropertyValue() lookup,
15340							 but we then use its camelCase styling to normalize it for manipulation. */
15341							var propertyName = CSS.Names.camelCase(property),
15342									valueData = parsePropertyValue(propertiesMap[property]);
15343
15344							/* Find shorthand color properties that have been passed a hex string. */
15345							/* Would be quicker to use CSS.Lists.colors.includes() if possible */
15346							if (_inArray(CSS.Lists.colors, propertyName)) {
15347								/* Parse the value data for each shorthand. */
15348								var endValue = valueData[0],
15349										easing = valueData[1],
15350										startValue = valueData[2];
15351
15352								if (CSS.RegEx.isHex.test(endValue)) {
15353									/* Convert the hex strings into their RGB component arrays. */
15354									var colorComponents = ["Red", "Green", "Blue"],
15355											endValueRGB = CSS.Values.hexToRgb(endValue),
15356											startValueRGB = startValue ? CSS.Values.hexToRgb(startValue) : undefined;
15357
15358									/* Inject the RGB component tweens into propertiesMap. */
15359									for (var i = 0; i < colorComponents.length; i++) {
15360										var dataArray = [endValueRGB[i]];
15361
15362										if (easing) {
15363											dataArray.push(easing);
15364										}
15365
15366										if (startValueRGB !== undefined) {
15367											dataArray.push(startValueRGB[i]);
15368										}
15369
15370										fixPropertyValue(propertyName + colorComponents[i], dataArray);
15371									}
15372									/* If we have replaced a shortcut color value then don't update the standard property name */
15373									continue;
15374								}
15375							}
15376							fixPropertyValue(propertyName, valueData);
15377						}
15378
15379						/* Along with its property data, store a reference to the element itself onto tweensContainer. */
15380						tweensContainer.element = element;
15381					}
15382
15383					/*****************
15384					 Call Push
15385					 *****************/
15386
15387					/* Note: tweensContainer can be empty if all of the properties in this call's property map were skipped due to not
15388					 being supported by the browser. The element property is used for checking that the tweensContainer has been appended to. */
15389					if (tweensContainer.element) {
15390						/* Apply the "velocity-animating" indicator class. */
15391						CSS.Values.addClass(element, "velocity-animating");
15392
15393						/* The call array houses the tweensContainers for each element being animated in the current call. */
15394						call.push(tweensContainer);
15395
15396						data = Data(element);
15397
15398						if (data) {
15399							/* Store the tweensContainer and options if we're working on the default effects queue, so that they can be used by the reverse command. */
15400							if (opts.queue === "") {
15401
15402								data.tweensContainer = tweensContainer;
15403								data.opts = opts;
15404							}
15405
15406							/* Switch on the element's animating flag. */
15407							data.isAnimating = true;
15408						}
15409
15410						/* Once the final element in this call's element set has been processed, push the call array onto
15411						 Velocity.State.calls for the animation tick to immediately begin processing. */
15412						if (elementsIndex === elementsLength - 1) {
15413							/* Add the current call plus its associated metadata (the element set and the call's options) onto the global call container.
15414							 Anything on this call container is subjected to tick() processing. */
15415							Velocity.State.calls.push([call, elements, opts, null, promiseData.resolver, null, 0]);
15416
15417							/* If the animation tick isn't running, start it. (Velocity shuts it off when there are no active calls to process.) */
15418							if (Velocity.State.isTicking === false) {
15419								Velocity.State.isTicking = true;
15420
15421								/* Start the tick loop. */
15422								tick();
15423							}
15424						} else {
15425							elementsIndex++;
15426						}
15427					}
15428				}
15429
15430				/* When the queue option is set to false, the call skips the element's queue and fires immediately. */
15431				if (opts.queue === false) {
15432					/* Since this buildQueue call doesn't respect the element's existing queue (which is where a delay option would have been appended),
15433					 we manually inject the delay property here with an explicit setTimeout. */
15434					if (opts.delay) {
15435
15436						/* Temporarily store delayed elements to facilitate access for global pause/resume */
15437						var callIndex = Velocity.State.delayedElements.count++;
15438						Velocity.State.delayedElements[callIndex] = element;
15439
15440						var delayComplete = (function(index) {
15441							return function() {
15442								/* Clear the temporary element */
15443								Velocity.State.delayedElements[index] = false;
15444
15445								/* Finally, issue the call */
15446								buildQueue();
15447							};
15448						})(callIndex);
15449
15450						Data(element).delayBegin = (new Date()).getTime();
15451						Data(element).delay = parseFloat(opts.delay);
15452						Data(element).delayTimer = {
15453							setTimeout: setTimeout(buildQueue, parseFloat(opts.delay)),
15454							next: delayComplete
15455						};
15456					} else {
15457						buildQueue();
15458					}
15459					/* Otherwise, the call undergoes element queueing as normal. */
15460					/* Note: To interoperate with jQuery, Velocity uses jQuery's own $.queue() stack for queuing logic. */
15461				} else {
15462					$.queue(element, opts.queue, function(next, clearQueue) {
15463						/* If the clearQueue flag was passed in by the stop command, resolve this call's promise. (Promises can only be resolved once,
15464						 so it's fine if this is repeatedly triggered for each element in the associated call.) */
15465						if (clearQueue === true) {
15466							if (promiseData.promise) {
15467								promiseData.resolver(elements);
15468							}
15469
15470							/* Do not continue with animation queueing. */
15471							return true;
15472						}
15473
15474						/* This flag indicates to the upcoming completeCall() function that this queue entry was initiated by Velocity.
15475						 See completeCall() for further details. */
15476						Velocity.velocityQueueEntryFlag = true;
15477
15478						buildQueue(next);
15479					});
15480				}
15481
15482				/*********************
15483				 Auto-Dequeuing
15484				 *********************/
15485
15486				/* As per jQuery's $.queue() behavior, to fire the first non-custom-queue entry on an element, the element
15487				 must be dequeued if its queue stack consists *solely* of the current call. (This can be determined by checking
15488				 for the "inprogress" item that jQuery prepends to active queue stack arrays.) Regardless, whenever the element's
15489				 queue is further appended with additional items -- including $.delay()'s or even $.animate() calls, the queue's
15490				 first entry is automatically fired. This behavior contrasts that of custom queues, which never auto-fire. */
15491				/* Note: When an element set is being subjected to a non-parallel Velocity call, the animation will not begin until
15492				 each one of the elements in the set has reached the end of its individually pre-existing queue chain. */
15493				/* Note: Unfortunately, most people don't fully grasp jQuery's powerful, yet quirky, $.queue() function.
15494				 Lean more here: http://stackoverflow.com/questions/1058158/can-somebody-explain-jquery-queue-to-me */
15495				if ((opts.queue === "" || opts.queue === "fx") && $.queue(element)[0] !== "inprogress") {
15496					$.dequeue(element);
15497				}
15498			}
15499
15500			/**************************
15501			 Element Set Iteration
15502			 **************************/
15503
15504			/* If the "nodeType" property exists on the elements variable, we're animating a single element.
15505			 Place it in an array so that $.each() can iterate over it. */
15506			$.each(elements, function(i, element) {
15507				/* Ensure each element in a set has a nodeType (is a real element) to avoid throwing errors. */
15508				if (Type.isNode(element)) {
15509					processElement(element, i);
15510				}
15511			});
15512
15513			/******************
15514			 Option: Loop
15515			 ******************/
15516
15517			/* The loop option accepts an integer indicating how many times the element should loop between the values in the
15518			 current call's properties map and the element's property values prior to this call. */
15519			/* Note: The loop option's logic is performed here -- after element processing -- because the current call needs
15520			 to undergo its queue insertion prior to the loop option generating its series of constituent "reverse" calls,
15521			 which chain after the current call. Two reverse calls (two "alternations") constitute one loop. */
15522			opts = $.extend({}, Velocity.defaults, options);
15523			opts.loop = parseInt(opts.loop, 10);
15524			var reverseCallsCount = (opts.loop * 2) - 1;
15525
15526			if (opts.loop) {
15527				/* Double the loop count to convert it into its appropriate number of "reverse" calls.
15528				 Subtract 1 from the resulting value since the current call is included in the total alternation count. */
15529				for (var x = 0; x < reverseCallsCount; x++) {
15530					/* Since the logic for the reverse action occurs inside Queueing and therefore this call's options object
15531					 isn't parsed until then as well, the current call's delay option must be explicitly passed into the reverse
15532					 call so that the delay logic that occurs inside *Pre-Queueing* can process it. */
15533					var reverseOptions = {
15534						delay: opts.delay,
15535						progress: opts.progress
15536					};
15537
15538					/* If a complete callback was passed into this call, transfer it to the loop redirect's final "reverse" call
15539					 so that it's triggered when the entire redirect is complete (and not when the very first animation is complete). */
15540					if (x === reverseCallsCount - 1) {
15541						reverseOptions.display = opts.display;
15542						reverseOptions.visibility = opts.visibility;
15543						reverseOptions.complete = opts.complete;
15544					}
15545
15546					animate(elements, "reverse", reverseOptions);
15547				}
15548			}
15549
15550			/***************
15551			 Chaining
15552			 ***************/
15553
15554			/* Return the elements back to the call chain, with wrapped elements taking precedence in case Velocity was called via the $.fn. extension. */
15555			return getChain();
15556		};
15557
15558		/* Turn Velocity into the animation function, extended with the pre-existing Velocity object. */
15559		Velocity = $.extend(animate, Velocity);
15560		/* For legacy support, also expose the literal animate method. */
15561		Velocity.animate = animate;
15562
15563		/**************
15564		 Timing
15565		 **************/
15566
15567		/* Ticker function. */
15568		var ticker = window.requestAnimationFrame || rAFShim;
15569
15570		/* Inactive browser tabs pause rAF, which results in all active animations immediately sprinting to their completion states when the tab refocuses.
15571		 To get around this, we dynamically switch rAF to setTimeout (which the browser *doesn't* pause) when the tab loses focus. We skip this for mobile
15572		 devices to avoid wasting battery power on inactive tabs. */
15573		/* Note: Tab focus detection doesn't work on older versions of IE, but that's okay since they don't support rAF to begin with. */
15574		if (!Velocity.State.isMobile && document.hidden !== undefined) {
15575			var updateTicker = function() {
15576				/* Reassign the rAF function (which the global tick() function uses) based on the tab's focus state. */
15577				if (document.hidden) {
15578					ticker = function(callback) {
15579						/* The tick function needs a truthy first argument in order to pass its internal timestamp check. */
15580						return setTimeout(function() {
15581							callback(true);
15582						}, 16);
15583					};
15584
15585					/* The rAF loop has been paused by the browser, so we manually restart the tick. */
15586					tick();
15587				} else {
15588					ticker = window.requestAnimationFrame || rAFShim;
15589				}
15590			};
15591
15592			/* Page could be sitting in the background at this time (i.e. opened as new tab) so making sure we use correct ticker from the start */
15593			updateTicker();
15594
15595			/* And then run check again every time visibility changes */
15596			document.addEventListener("visibilitychange", updateTicker);
15597		}
15598
15599		/************
15600		 Tick
15601		 ************/
15602
15603		/* Note: All calls to Velocity are pushed to the Velocity.State.calls array, which is fully iterated through upon each tick. */
15604		function tick(timestamp) {
15605			/* An empty timestamp argument indicates that this is the first tick occurence since ticking was turned on.
15606			 We leverage this metadata to fully ignore the first tick pass since RAF's initial pass is fired whenever
15607			 the browser's next tick sync time occurs, which results in the first elements subjected to Velocity
15608			 calls being animated out of sync with any elements animated immediately thereafter. In short, we ignore
15609			 the first RAF tick pass so that elements being immediately consecutively animated -- instead of simultaneously animated
15610			 by the same Velocity call -- are properly batched into the same initial RAF tick and consequently remain in sync thereafter. */
15611			if (timestamp) {
15612				/* We normally use RAF's high resolution timestamp but as it can be significantly offset when the browser is
15613				 under high stress we give the option for choppiness over allowing the browser to drop huge chunks of frames.
15614				 We use performance.now() and shim it if it doesn't exist for when the tab is hidden. */
15615				var timeCurrent = Velocity.timestamp && timestamp !== true ? timestamp : performance.now();
15616
15617				/********************
15618				 Call Iteration
15619				 ********************/
15620
15621				var callsLength = Velocity.State.calls.length;
15622
15623				/* To speed up iterating over this array, it is compacted (falsey items -- calls that have completed -- are removed)
15624				 when its length has ballooned to a point that can impact tick performance. This only becomes necessary when animation
15625				 has been continuous with many elements over a long period of time; whenever all active calls are completed, completeCall() clears Velocity.State.calls. */
15626				if (callsLength > 10000) {
15627					Velocity.State.calls = compactSparseArray(Velocity.State.calls);
15628					callsLength = Velocity.State.calls.length;
15629				}
15630
15631				/* Iterate through each active call. */
15632				for (var i = 0; i < callsLength; i++) {
15633					/* When a Velocity call is completed, its Velocity.State.calls entry is set to false. Continue on to the next call. */
15634					if (!Velocity.State.calls[i]) {
15635						continue;
15636					}
15637
15638					/************************
15639					 Call-Wide Variables
15640					 ************************/
15641
15642					var callContainer = Velocity.State.calls[i],
15643							call = callContainer[0],
15644							opts = callContainer[2],
15645							timeStart = callContainer[3],
15646							firstTick = !timeStart,
15647							tweenDummyValue = null,
15648							pauseObject = callContainer[5],
15649							millisecondsEllapsed = callContainer[6];
15650
15651
15652
15653					/* If timeStart is undefined, then this is the first time that this call has been processed by tick().
15654					 We assign timeStart now so that its value is as close to the real animation start time as possible.
15655					 (Conversely, had timeStart been defined when this call was added to Velocity.State.calls, the delay
15656					 between that time and now would cause the first few frames of the tween to be skipped since
15657					 percentComplete is calculated relative to timeStart.) */
15658					/* Further, subtract 16ms (the approximate resolution of RAF) from the current time value so that the
15659					 first tick iteration isn't wasted by animating at 0% tween completion, which would produce the
15660					 same style value as the element's current value. */
15661					if (!timeStart) {
15662						timeStart = Velocity.State.calls[i][3] = timeCurrent - 16;
15663					}
15664
15665					/* If a pause object is present, skip processing unless it has been set to resume */
15666					if (pauseObject) {
15667						if (pauseObject.resume === true) {
15668							/* Update the time start to accomodate the paused completion amount */
15669							timeStart = callContainer[3] = Math.round(timeCurrent - millisecondsEllapsed - 16);
15670
15671							/* Remove pause object after processing */
15672							callContainer[5] = null;
15673						} else {
15674							continue;
15675						}
15676					}
15677
15678					millisecondsEllapsed = callContainer[6] = timeCurrent - timeStart;
15679
15680					/* The tween's completion percentage is relative to the tween's start time, not the tween's start value
15681					 (which would result in unpredictable tween durations since JavaScript's timers are not particularly accurate).
15682					 Accordingly, we ensure that percentComplete does not exceed 1. */
15683					var percentComplete = Math.min((millisecondsEllapsed) / opts.duration, 1);
15684
15685					/**********************
15686					 Element Iteration
15687					 **********************/
15688
15689					/* For every call, iterate through each of the elements in its set. */
15690					for (var j = 0, callLength = call.length; j < callLength; j++) {
15691						var tweensContainer = call[j],
15692								element = tweensContainer.element;
15693
15694						/* Check to see if this element has been deleted midway through the animation by checking for the
15695						 continued existence of its data cache. If it's gone, or the element is currently paused, skip animating this element. */
15696						if (!Data(element)) {
15697							continue;
15698						}
15699
15700						var transformPropertyExists = false;
15701
15702						/**********************************
15703						 Display & Visibility Toggling
15704						 **********************************/
15705
15706						/* If the display option is set to non-"none", set it upfront so that the element can become visible before tweening begins.
15707						 (Otherwise, display's "none" value is set in completeCall() once the animation has completed.) */
15708						if (opts.display !== undefined && opts.display !== null && opts.display !== "none") {
15709							if (opts.display === "flex") {
15710								var flexValues = ["-webkit-box", "-moz-box", "-ms-flexbox", "-webkit-flex"];
15711
15712								$.each(flexValues, function(i, flexValue) {
15713									CSS.setPropertyValue(element, "display", flexValue);
15714								});
15715							}
15716
15717							CSS.setPropertyValue(element, "display", opts.display);
15718						}
15719
15720						/* Same goes with the visibility option, but its "none" equivalent is "hidden". */
15721						if (opts.visibility !== undefined && opts.visibility !== "hidden") {
15722							CSS.setPropertyValue(element, "visibility", opts.visibility);
15723						}
15724
15725						/************************
15726						 Property Iteration
15727						 ************************/
15728
15729						/* For every element, iterate through each property. */
15730						for (var property in tweensContainer) {
15731							/* Note: In addition to property tween data, tweensContainer contains a reference to its associated element. */
15732							if (tweensContainer.hasOwnProperty(property) && property !== "element") {
15733								var tween = tweensContainer[property],
15734										currentValue,
15735										/* Easing can either be a pre-genereated function or a string that references a pre-registered easing
15736										 on the Velocity.Easings object. In either case, return the appropriate easing *function*. */
15737										easing = Type.isString(tween.easing) ? Velocity.Easings[tween.easing] : tween.easing;
15738
15739								/******************************
15740								 Current Value Calculation
15741								 ******************************/
15742
15743								if (Type.isString(tween.pattern)) {
15744									var patternReplace = percentComplete === 1 ?
15745											function($0, index, round) {
15746												var result = tween.endValue[index];
15747
15748												return round ? Math.round(result) : result;
15749											} :
15750											function($0, index, round) {
15751												var startValue = tween.startValue[index],
15752														tweenDelta = tween.endValue[index] - startValue,
15753														result = startValue + (tweenDelta * easing(percentComplete, opts, tweenDelta));
15754
15755												return round ? Math.round(result) : result;
15756											};
15757
15758									currentValue = tween.pattern.replace(/{(\d+)(!)?}/g, patternReplace);
15759								} else if (percentComplete === 1) {
15760									/* If this is the last tick pass (if we've reached 100% completion for this tween),
15761									 ensure that currentValue is explicitly set to its target endValue so that it's not subjected to any rounding. */
15762									currentValue = tween.endValue;
15763								} else {
15764									/* Otherwise, calculate currentValue based on the current delta from startValue. */
15765									var tweenDelta = tween.endValue - tween.startValue;
15766
15767									currentValue = tween.startValue + (tweenDelta * easing(percentComplete, opts, tweenDelta));
15768									/* If no value change is occurring, don't proceed with DOM updating. */
15769								}
15770								if (!firstTick && (currentValue === tween.currentValue)) {
15771									continue;
15772								}
15773
15774								tween.currentValue = currentValue;
15775
15776								/* If we're tweening a fake 'tween' property in order to log transition values, update the one-per-call variable so that
15777								 it can be passed into the progress callback. */
15778								if (property === "tween") {
15779									tweenDummyValue = currentValue;
15780								} else {
15781									/******************
15782									 Hooks: Part I
15783									 ******************/
15784									var hookRoot;
15785
15786									/* For hooked properties, the newly-updated rootPropertyValueCache is cached onto the element so that it can be used
15787									 for subsequent hooks in this call that are associated with the same root property. If we didn't cache the updated
15788									 rootPropertyValue, each subsequent update to the root property in this tick pass would reset the previous hook's
15789									 updates to rootPropertyValue prior to injection. A nice performance byproduct of rootPropertyValue caching is that
15790									 subsequently chained animations using the same hookRoot but a different hook can use this cached rootPropertyValue. */
15791									if (CSS.Hooks.registered[property]) {
15792										hookRoot = CSS.Hooks.getRoot(property);
15793
15794										var rootPropertyValueCache = Data(element).rootPropertyValueCache[hookRoot];
15795
15796										if (rootPropertyValueCache) {
15797											tween.rootPropertyValue = rootPropertyValueCache;
15798										}
15799									}
15800
15801									/*****************
15802									 DOM Update
15803									 *****************/
15804
15805									/* setPropertyValue() returns an array of the property name and property value post any normalization that may have been performed. */
15806									/* Note: To solve an IE<=8 positioning bug, the unit type is dropped when setting a property value of 0. */
15807									var adjustedSetData = CSS.setPropertyValue(element, /* SET */
15808											property,
15809											tween.currentValue + (IE < 9 && parseFloat(currentValue) === 0 ? "" : tween.unitType),
15810											tween.rootPropertyValue,
15811											tween.scrollData);
15812
15813									/*******************
15814									 Hooks: Part II
15815									 *******************/
15816
15817									/* Now that we have the hook's updated rootPropertyValue (the post-processed value provided by adjustedSetData), cache it onto the element. */
15818									if (CSS.Hooks.registered[property]) {
15819										/* Since adjustedSetData contains normalized data ready for DOM updating, the rootPropertyValue needs to be re-extracted from its normalized form. ?? */
15820										if (CSS.Normalizations.registered[hookRoot]) {
15821											Data(element).rootPropertyValueCache[hookRoot] = CSS.Normalizations.registered[hookRoot]("extract", null, adjustedSetData[1]);
15822										} else {
15823											Data(element).rootPropertyValueCache[hookRoot] = adjustedSetData[1];
15824										}
15825									}
15826
15827									/***************
15828									 Transforms
15829									 ***************/
15830
15831									/* Flag whether a transform property is being animated so that flushTransformCache() can be triggered once this tick pass is complete. */
15832									if (adjustedSetData[0] === "transform") {
15833										transformPropertyExists = true;
15834									}
15835
15836								}
15837							}
15838						}
15839
15840						/****************
15841						 mobileHA
15842						 ****************/
15843
15844						/* If mobileHA is enabled, set the translate3d transform to null to force hardware acceleration.
15845						 It's safe to override this property since Velocity doesn't actually support its animation (hooks are used in its place). */
15846						if (opts.mobileHA) {
15847							/* Don't set the null transform hack if we've already done so. */
15848							if (Data(element).transformCache.translate3d === undefined) {
15849								/* All entries on the transformCache object are later concatenated into a single transform string via flushTransformCache(). */
15850								Data(element).transformCache.translate3d = "(0px, 0px, 0px)";
15851
15852								transformPropertyExists = true;
15853							}
15854						}
15855
15856						if (transformPropertyExists) {
15857							CSS.flushTransformCache(element);
15858						}
15859					}
15860
15861					/* The non-"none" display value is only applied to an element once -- when its associated call is first ticked through.
15862					 Accordingly, it's set to false so that it isn't re-processed by this call in the next tick. */
15863					if (opts.display !== undefined && opts.display !== "none") {
15864						Velocity.State.calls[i][2].display = false;
15865					}
15866					if (opts.visibility !== undefined && opts.visibility !== "hidden") {
15867						Velocity.State.calls[i][2].visibility = false;
15868					}
15869
15870					/* Pass the elements and the timing data (percentComplete, msRemaining, timeStart, tweenDummyValue) into the progress callback. */
15871					if (opts.progress) {
15872						opts.progress.call(callContainer[1],
15873								callContainer[1],
15874								percentComplete,
15875								Math.max(0, (timeStart + opts.duration) - timeCurrent),
15876								timeStart,
15877								tweenDummyValue);
15878					}
15879
15880					/* If this call has finished tweening, pass its index to completeCall() to handle call cleanup. */
15881					if (percentComplete === 1) {
15882						completeCall(i);
15883					}
15884				}
15885			}
15886
15887			/* Note: completeCall() sets the isTicking flag to false when the last call on Velocity.State.calls has completed. */
15888			if (Velocity.State.isTicking) {
15889				ticker(tick);
15890			}
15891		}
15892
15893		/**********************
15894		 Call Completion
15895		 **********************/
15896
15897		/* Note: Unlike tick(), which processes all active calls at once, call completion is handled on a per-call basis. */
15898		function completeCall(callIndex, isStopped) {
15899			/* Ensure the call exists. */
15900			if (!Velocity.State.calls[callIndex]) {
15901				return false;
15902			}
15903
15904			/* Pull the metadata from the call. */
15905			var call = Velocity.State.calls[callIndex][0],
15906					elements = Velocity.State.calls[callIndex][1],
15907					opts = Velocity.State.calls[callIndex][2],
15908					resolver = Velocity.State.calls[callIndex][4];
15909
15910			var remainingCallsExist = false;
15911
15912			/*************************
15913			 Element Finalization
15914			 *************************/
15915
15916			for (var i = 0, callLength = call.length; i < callLength; i++) {
15917				var element = call[i].element;
15918
15919				/* If the user set display to "none" (intending to hide the element), set it now that the animation has completed. */
15920				/* Note: display:none isn't set when calls are manually stopped (via Velocity("stop"). */
15921				/* Note: Display gets ignored with "reverse" calls and infinite loops, since this behavior would be undesirable. */
15922				if (!isStopped && !opts.loop) {
15923					if (opts.display === "none") {
15924						CSS.setPropertyValue(element, "display", opts.display);
15925					}
15926
15927					if (opts.visibility === "hidden") {
15928						CSS.setPropertyValue(element, "visibility", opts.visibility);
15929					}
15930				}
15931
15932				/* If the element's queue is empty (if only the "inprogress" item is left at position 0) or if its queue is about to run
15933				 a non-Velocity-initiated entry, turn off the isAnimating flag. A non-Velocity-initiatied queue entry's logic might alter
15934				 an element's CSS values and thereby cause Velocity's cached value data to go stale. To detect if a queue entry was initiated by Velocity,
15935				 we check for the existence of our special Velocity.queueEntryFlag declaration, which minifiers won't rename since the flag
15936				 is assigned to jQuery's global $ object and thus exists out of Velocity's own scope. */
15937				var data = Data(element);
15938
15939				if (opts.loop !== true && ($.queue(element)[1] === undefined || !/\.velocityQueueEntryFlag/i.test($.queue(element)[1]))) {
15940					/* The element may have been deleted. Ensure that its data cache still exists before acting on it. */
15941					if (data) {
15942						data.isAnimating = false;
15943						/* Clear the element's rootPropertyValueCache, which will become stale. */
15944						data.rootPropertyValueCache = {};
15945
15946						var transformHAPropertyExists = false;
15947						/* If any 3D transform subproperty is at its default value (regardless of unit type), remove it. */
15948						$.each(CSS.Lists.transforms3D, function(i, transformName) {
15949							var defaultValue = /^scale/.test(transformName) ? 1 : 0,
15950									currentValue = data.transformCache[transformName];
15951
15952							if (data.transformCache[transformName] !== undefined && new RegExp("^\\(" + defaultValue + "[^.]").test(currentValue)) {
15953								transformHAPropertyExists = true;
15954
15955								delete data.transformCache[transformName];
15956							}
15957						});
15958
15959						/* Mobile devices have hardware acceleration removed at the end of the animation in order to avoid hogging the GPU's memory. */
15960						if (opts.mobileHA) {
15961							transformHAPropertyExists = true;
15962							delete data.transformCache.translate3d;
15963						}
15964
15965						/* Flush the subproperty removals to the DOM. */
15966						if (transformHAPropertyExists) {
15967							CSS.flushTransformCache(element);
15968						}
15969
15970						/* Remove the "velocity-animating" indicator class. */
15971						CSS.Values.removeClass(element, "velocity-animating");
15972					}
15973				}
15974
15975				/*********************
15976				 Option: Complete
15977				 *********************/
15978
15979				/* Complete is fired once per call (not once per element) and is passed the full raw DOM element set as both its context and its first argument. */
15980				/* Note: Callbacks aren't fired when calls are manually stopped (via Velocity("stop"). */
15981				if (!isStopped && opts.complete && !opts.loop && (i === callLength - 1)) {
15982					/* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */
15983					try {
15984						opts.complete.call(elements, elements);
15985					} catch (error) {
15986						setTimeout(function() {
15987							throw error;
15988						}, 1);
15989					}
15990				}
15991
15992				/**********************
15993				 Promise Resolving
15994				 **********************/
15995
15996				/* Note: Infinite loops don't return promises. */
15997				if (resolver && opts.loop !== true) {
15998					resolver(elements);
15999				}
16000
16001				/****************************
16002				 Option: Loop (Infinite)
16003				 ****************************/
16004
16005				if (data && opts.loop === true && !isStopped) {
16006					/* If a rotateX/Y/Z property is being animated by 360 deg with loop:true, swap tween start/end values to enable
16007					 continuous iterative rotation looping. (Otherise, the element would just rotate back and forth.) */
16008					$.each(data.tweensContainer, function(propertyName, tweenContainer) {
16009						if (/^rotate/.test(propertyName) && ((parseFloat(tweenContainer.startValue) - parseFloat(tweenContainer.endValue)) % 360 === 0)) {
16010							var oldStartValue = tweenContainer.startValue;
16011
16012							tweenContainer.startValue = tweenContainer.endValue;
16013							tweenContainer.endValue = oldStartValue;
16014						}
16015
16016						if (/^backgroundPosition/.test(propertyName) && parseFloat(tweenContainer.endValue) === 100 && tweenContainer.unitType === "%") {
16017							tweenContainer.endValue = 0;
16018							tweenContainer.startValue = 100;
16019						}
16020					});
16021
16022					Velocity(element, "reverse", {loop: true, delay: opts.delay});
16023				}
16024
16025				/***************
16026				 Dequeueing
16027				 ***************/
16028
16029				/* Fire the next call in the queue so long as this call's queue wasn't set to false (to trigger a parallel animation),
16030				 which would have already caused the next call to fire. Note: Even if the end of the animation queue has been reached,
16031				 $.dequeue() must still be called in order to completely clear jQuery's animation queue. */
16032				if (opts.queue !== false) {
16033					$.dequeue(element, opts.queue);
16034				}
16035			}
16036
16037			/************************
16038			 Calls Array Cleanup
16039			 ************************/
16040
16041			/* Since this call is complete, set it to false so that the rAF tick skips it. This array is later compacted via compactSparseArray().
16042			 (For performance reasons, the call is set to false instead of being deleted from the array: http://www.html5rocks.com/en/tutorials/speed/v8/) */
16043			Velocity.State.calls[callIndex] = false;
16044
16045			/* Iterate through the calls array to determine if this was the final in-progress animation.
16046			 If so, set a flag to end ticking and clear the calls array. */
16047			for (var j = 0, callsLength = Velocity.State.calls.length; j < callsLength; j++) {
16048				if (Velocity.State.calls[j] !== false) {
16049					remainingCallsExist = true;
16050
16051					break;
16052				}
16053			}
16054
16055			if (remainingCallsExist === false) {
16056				/* tick() will detect this flag upon its next iteration and subsequently turn itself off. */
16057				Velocity.State.isTicking = false;
16058
16059				/* Clear the calls array so that its length is reset. */
16060				delete Velocity.State.calls;
16061				Velocity.State.calls = [];
16062			}
16063		}
16064
16065		/******************
16066		 Frameworks
16067		 ******************/
16068
16069		/* Both jQuery and Zepto allow their $.fn object to be extended to allow wrapped elements to be subjected to plugin calls.
16070		 If either framework is loaded, register a "velocity" extension pointing to Velocity's core animate() method.  Velocity
16071		 also registers itself onto a global container (window.jQuery || window.Zepto || window) so that certain features are
16072		 accessible beyond just a per-element scope. This master object contains an .animate() method, which is later assigned to $.fn
16073		 (if jQuery or Zepto are present). Accordingly, Velocity can both act on wrapped DOM elements and stand alone for targeting raw DOM elements. */
16074		global.Velocity = Velocity;
16075
16076		if (global !== window) {
16077			/* Assign the element function to Velocity's core animate() method. */
16078			global.fn.velocity = animate;
16079			/* Assign the object function's defaults to Velocity's global defaults object. */
16080			global.fn.velocity.defaults = Velocity.defaults;
16081		}
16082
16083		/***********************
16084		 Packaged Redirects
16085		 ***********************/
16086
16087		/* slideUp, slideDown */
16088		$.each(["Down", "Up"], function(i, direction) {
16089			Velocity.Redirects["slide" + direction] = function(element, options, elementsIndex, elementsSize, elements, promiseData) {
16090				var opts = $.extend({}, options),
16091						begin = opts.begin,
16092						complete = opts.complete,
16093						inlineValues = {},
16094						computedValues = {height: "", marginTop: "", marginBottom: "", paddingTop: "", paddingBottom: ""};
16095
16096				if (opts.display === undefined) {
16097					/* Show the element before slideDown begins and hide the element after slideUp completes. */
16098					/* Note: Inline elements cannot have dimensions animated, so they're reverted to inline-block. */
16099					opts.display = (direction === "Down" ? (Velocity.CSS.Values.getDisplayType(element) === "inline" ? "inline-block" : "block") : "none");
16100				}
16101
16102				opts.begin = function() {
16103					/* If the user passed in a begin callback, fire it now. */
16104					if (elementsIndex === 0 && begin) {
16105						begin.call(elements, elements);
16106					}
16107
16108					/* Cache the elements' original vertical dimensional property values so that we can animate back to them. */
16109					for (var property in computedValues) {
16110						if (!computedValues.hasOwnProperty(property)) {
16111							continue;
16112						}
16113						inlineValues[property] = element.style[property];
16114
16115						/* For slideDown, use forcefeeding to animate all vertical properties from 0. For slideUp,
16116						 use forcefeeding to start from computed values and animate down to 0. */
16117						var propertyValue = CSS.getPropertyValue(element, property);
16118						computedValues[property] = (direction === "Down") ? [propertyValue, 0] : [0, propertyValue];
16119					}
16120
16121					/* Force vertical overflow content to clip so that sliding works as expected. */
16122					inlineValues.overflow = element.style.overflow;
16123					element.style.overflow = "hidden";
16124				};
16125
16126				opts.complete = function() {
16127					/* Reset element to its pre-slide inline values once its slide animation is complete. */
16128					for (var property in inlineValues) {
16129						if (inlineValues.hasOwnProperty(property)) {
16130							element.style[property] = inlineValues[property];
16131						}
16132					}
16133
16134					/* If the user passed in a complete callback, fire it now. */
16135					if (elementsIndex === elementsSize - 1) {
16136						if (complete) {
16137							complete.call(elements, elements);
16138						}
16139						if (promiseData) {
16140							promiseData.resolver(elements);
16141						}
16142					}
16143				};
16144
16145				Velocity(element, computedValues, opts);
16146			};
16147		});
16148
16149		/* fadeIn, fadeOut */
16150		$.each(["In", "Out"], function(i, direction) {
16151			Velocity.Redirects["fade" + direction] = function(element, options, elementsIndex, elementsSize, elements, promiseData) {
16152				var opts = $.extend({}, options),
16153						complete = opts.complete,
16154						propertiesMap = {opacity: (direction === "In") ? 1 : 0};
16155
16156				/* Since redirects are triggered individually for each element in the animated set, avoid repeatedly triggering
16157				 callbacks by firing them only when the final element has been reached. */
16158				if (elementsIndex !== 0) {
16159					opts.begin = null;
16160				}
16161				if (elementsIndex !== elementsSize - 1) {
16162					opts.complete = null;
16163				} else {
16164					opts.complete = function() {
16165						if (complete) {
16166							complete.call(elements, elements);
16167						}
16168						if (promiseData) {
16169							promiseData.resolver(elements);
16170						}
16171					};
16172				}
16173
16174				/* If a display was passed in, use it. Otherwise, default to "none" for fadeOut or the element-specific default for fadeIn. */
16175				/* Note: We allow users to pass in "null" to skip display setting altogether. */
16176				if (opts.display === undefined) {
16177					opts.display = (direction === "In" ? "auto" : "none");
16178				}
16179
16180				Velocity(this, propertiesMap, opts);
16181			};
16182		});
16183
16184		return Velocity;
16185	}((window.jQuery || window.Zepto || window), window, (window ? window.document : undefined));
16186}));
16187
16188/******************
16189 Known Issues
16190 ******************/
16191
16192/* The CSS spec mandates that the translateX/Y/Z transforms are %-relative to the element itself -- not its parent.
16193 Velocity, however, doesn't make this distinction. Thus, converting to or from the % unit with these subproperties
16194 will produce an inaccurate conversion value. The same issue exists with the cx/cy attributes of SVG circles and ellipses. */
16195
16196},{}],55:[function(require,module,exports){
16197/**********************
16198 Velocity UI Pack
16199 **********************/
16200
16201/* VelocityJS.org UI Pack (5.2.0). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License. Portions copyright Daniel Eden, Christian Pucci. */
16202
16203(function(factory) {
16204	"use strict";
16205	/* CommonJS module. */
16206	if (typeof require === "function" && typeof exports === "object") {
16207		module.exports = factory();
16208		/* AMD module. */
16209	} else if (typeof define === "function" && define.amd) {
16210		define(["velocity"], factory);
16211		/* Browser globals. */
16212	} else {
16213		factory();
16214	}
16215}(function() {
16216	"use strict";
16217	return function(global, window, document, undefined) {
16218
16219		/*************
16220		 Checks
16221		 *************/
16222		var Velocity = global.Velocity;
16223
16224		if (!Velocity || !Velocity.Utilities) {
16225			if (window.console) {
16226				console.log("Velocity UI Pack: Velocity must be loaded first. Aborting.");
16227			}
16228			return;
16229		}
16230		var $ = Velocity.Utilities;
16231
16232		var velocityVersion = Velocity.version,
16233				requiredVersion = {major: 1, minor: 1, patch: 0};
16234
16235		function greaterSemver(primary, secondary) {
16236			var versionInts = [];
16237
16238			if (!primary || !secondary) {
16239				return false;
vendor: 27,195 bytes, lines 16240-17002
16240			}
16241
16242			$.each([primary, secondary], function(i, versionObject) {
16243				var versionIntsComponents = [];
16244
16245				$.each(versionObject, function(component, value) {
16246					while (value.toString().length < 5) {
16247						value = "0" + value;
16248					}
16249					versionIntsComponents.push(value);
16250				});
16251
16252				versionInts.push(versionIntsComponents.join(""));
16253			});
16254
16255			return (parseFloat(versionInts[0]) > parseFloat(versionInts[1]));
16256		}
16257
16258		if (greaterSemver(requiredVersion, velocityVersion)) {
16259			var abortError = "Velocity UI Pack: You need to update Velocity (velocity.js) to a newer version. Visit http://github.com/julianshapiro/velocity.";
16260			alert(abortError);
16261			throw new Error(abortError);
16262		}
16263
16264		/************************
16265		 Effect Registration
16266		 ************************/
16267
16268		/* Note: RegisterUI is a legacy name. */
16269		Velocity.RegisterEffect = Velocity.RegisterUI = function(effectName, properties) {
16270			/* Animate the expansion/contraction of the elements' parent's height for In/Out effects. */
16271			function animateParentHeight(elements, direction, totalDuration, stagger) {
16272				var totalHeightDelta = 0,
16273						parentNode;
16274
16275				/* Sum the total height (including padding and margin) of all targeted elements. */
16276				$.each(elements.nodeType ? [elements] : elements, function(i, element) {
16277					if (stagger) {
16278						/* Increase the totalDuration by the successive delay amounts produced by the stagger option. */
16279						totalDuration += i * stagger;
16280					}
16281
16282					parentNode = element.parentNode;
16283
16284					var propertiesToSum = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom"];
16285
16286					/* If box-sizing is border-box, the height already includes padding and margin */
16287					if (Velocity.CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() === "border-box") {
16288						propertiesToSum = ["height"];
16289					}
16290
16291					$.each(propertiesToSum, function(i, property) {
16292						totalHeightDelta += parseFloat(Velocity.CSS.getPropertyValue(element, property));
16293					});
16294				});
16295
16296				/* Animate the parent element's height adjustment (with a varying duration multiplier for aesthetic benefits). */
16297				Velocity.animate(
16298						parentNode,
16299						{height: (direction === "In" ? "+" : "-") + "=" + totalHeightDelta},
16300						{queue: false, easing: "ease-in-out", duration: totalDuration * (direction === "In" ? 0.6 : 1)}
16301				);
16302			}
16303
16304			/* Register a custom redirect for each effect. */
16305			Velocity.Redirects[effectName] = function(element, redirectOptions, elementsIndex, elementsSize, elements, promiseData, loop) {
16306				var finalElement = (elementsIndex === elementsSize - 1),
16307						totalDuration = 0;
16308
16309				loop = loop || properties.loop;
16310				if (typeof properties.defaultDuration === "function") {
16311					properties.defaultDuration = properties.defaultDuration.call(elements, elements);
16312				} else {
16313					properties.defaultDuration = parseFloat(properties.defaultDuration);
16314				}
16315
16316				/* Get the total duration used, so we can share it out with everything that doesn't have a duration */
16317				for (var callIndex = 0; callIndex < properties.calls.length; callIndex++) {
16318					durationPercentage = properties.calls[callIndex][1];
16319					if (typeof durationPercentage === "number") {
16320						totalDuration += durationPercentage;
16321					}
16322				}
16323				var shareDuration = totalDuration >= 1 ? 0 : properties.calls.length ? (1 - totalDuration) / properties.calls.length : 1;
16324
16325				/* Iterate through each effect's call array. */
16326				for (callIndex = 0; callIndex < properties.calls.length; callIndex++) {
16327					var call = properties.calls[callIndex],
16328							propertyMap = call[0],
16329							redirectDuration = 1000,
16330							durationPercentage = call[1],
16331							callOptions = call[2] || {},
16332							opts = {};
16333
16334					if (redirectOptions.duration !== undefined) {
16335						redirectDuration = redirectOptions.duration;
16336					} else if (properties.defaultDuration !== undefined) {
16337						redirectDuration = properties.defaultDuration;
16338					}
16339
16340					/* Assign the whitelisted per-call options. */
16341					opts.duration = redirectDuration * (typeof durationPercentage === "number" ? durationPercentage : shareDuration);
16342					opts.queue = redirectOptions.queue || "";
16343					opts.easing = callOptions.easing || "ease";
16344					opts.delay = parseFloat(callOptions.delay) || 0;
16345					opts.loop = !properties.loop && callOptions.loop;
16346					opts._cacheValues = callOptions._cacheValues || true;
16347
16348					/* Special processing for the first effect call. */
16349					if (callIndex === 0) {
16350						/* If a delay was passed into the redirect, combine it with the first call's delay. */
16351						opts.delay += (parseFloat(redirectOptions.delay) || 0);
16352
16353						if (elementsIndex === 0) {
16354							opts.begin = function() {
16355								/* Only trigger a begin callback on the first effect call with the first element in the set. */
16356								if (redirectOptions.begin) {
16357									redirectOptions.begin.call(elements, elements);
16358								}
16359
16360								var direction = effectName.match(/(In|Out)$/);
16361
16362								/* Make "in" transitioning elements invisible immediately so that there's no FOUC between now
16363								 and the first RAF tick. */
16364								if ((direction && direction[0] === "In") && propertyMap.opacity !== undefined) {
16365									$.each(elements.nodeType ? [elements] : elements, function(i, element) {
16366										Velocity.CSS.setPropertyValue(element, "opacity", 0);
16367									});
16368								}
16369
16370								/* Only trigger animateParentHeight() if we're using an In/Out transition. */
16371								if (redirectOptions.animateParentHeight && direction) {
16372									animateParentHeight(elements, direction[0], redirectDuration + opts.delay, redirectOptions.stagger);
16373								}
16374							};
16375						}
16376
16377						/* If the user isn't overriding the display option, default to "auto" for "In"-suffixed transitions. */
16378						if (redirectOptions.display !== null) {
16379							if (redirectOptions.display !== undefined && redirectOptions.display !== "none") {
16380								opts.display = redirectOptions.display;
16381							} else if (/In$/.test(effectName)) {
16382								/* Inline elements cannot be subjected to transforms, so we switch them to inline-block. */
16383								var defaultDisplay = Velocity.CSS.Values.getDisplayType(element);
16384								opts.display = (defaultDisplay === "inline") ? "inline-block" : defaultDisplay;
16385							}
16386						}
16387
16388						if (redirectOptions.visibility && redirectOptions.visibility !== "hidden") {
16389							opts.visibility = redirectOptions.visibility;
16390						}
16391					}
16392
16393					/* Special processing for the last effect call. */
16394					if (callIndex === properties.calls.length - 1) {
16395						/* Append promise resolving onto the user's redirect callback. */
16396						var injectFinalCallbacks = function() {
16397							if ((redirectOptions.display === undefined || redirectOptions.display === "none") && /Out$/.test(effectName)) {
16398								$.each(elements.nodeType ? [elements] : elements, function(i, element) {
16399									Velocity.CSS.setPropertyValue(element, "display", "none");
16400								});
16401							}
16402							if (redirectOptions.complete) {
16403								redirectOptions.complete.call(elements, elements);
16404							}
16405							if (promiseData) {
16406								promiseData.resolver(elements || element);
16407							}
16408						};
16409
16410						opts.complete = function() {
16411							if (loop) {
16412								Velocity.Redirects[effectName](element, redirectOptions, elementsIndex, elementsSize, elements, promiseData, loop === true ? true : Math.max(0, loop - 1));
16413							}
16414							if (properties.reset) {
16415								for (var resetProperty in properties.reset) {
16416									if (!properties.reset.hasOwnProperty(resetProperty)) {
16417										continue;
16418									}
16419									var resetValue = properties.reset[resetProperty];
16420
16421									/* Format each non-array value in the reset property map to [ value, value ] so that changes apply
16422									 immediately and DOM querying is avoided (via forcefeeding). */
16423									/* Note: Don't forcefeed hooks, otherwise their hook roots will be defaulted to their null values. */
16424									if (Velocity.CSS.Hooks.registered[resetProperty] === undefined && (typeof resetValue === "string" || typeof resetValue === "number")) {
16425										properties.reset[resetProperty] = [properties.reset[resetProperty], properties.reset[resetProperty]];
16426									}
16427								}
16428
16429								/* So that the reset values are applied instantly upon the next rAF tick, use a zero duration and parallel queueing. */
16430								var resetOptions = {duration: 0, queue: false};
16431
16432								/* Since the reset option uses up the complete callback, we trigger the user's complete callback at the end of ours. */
16433								if (finalElement) {
16434									resetOptions.complete = injectFinalCallbacks;
16435								}
16436
16437								Velocity.animate(element, properties.reset, resetOptions);
16438								/* Only trigger the user's complete callback on the last effect call with the last element in the set. */
16439							} else if (finalElement) {
16440								injectFinalCallbacks();
16441							}
16442						};
16443
16444						if (redirectOptions.visibility === "hidden") {
16445							opts.visibility = redirectOptions.visibility;
16446						}
16447					}
16448
16449					Velocity.animate(element, propertyMap, opts);
16450				}
16451			};
16452
16453			/* Return the Velocity object so that RegisterUI calls can be chained. */
16454			return Velocity;
16455		};
16456
16457		/*********************
16458		 Packaged Effects
16459		 *********************/
16460
16461		/* Externalize the packagedEffects data so that they can optionally be modified and re-registered. */
16462		/* Support: <=IE8: Callouts will have no effect, and transitions will simply fade in/out. IE9/Android 2.3: Most effects are fully supported, the rest fade in/out. All other browsers: full support. */
16463		Velocity.RegisterEffect.packagedEffects =
16464				{
16465					/* Animate.css */
16466					"callout.bounce": {
16467						defaultDuration: 550,
16468						calls: [
16469							[{translateY: -30}, 0.25],
16470							[{translateY: 0}, 0.125],
16471							[{translateY: -15}, 0.125],
16472							[{translateY: 0}, 0.25]
16473						]
16474					},
16475					/* Animate.css */
16476					"callout.shake": {
16477						defaultDuration: 800,
16478						calls: [
16479							[{translateX: -11}],
16480							[{translateX: 11}],
16481							[{translateX: -11}],
16482							[{translateX: 11}],
16483							[{translateX: -11}],
16484							[{translateX: 11}],
16485							[{translateX: -11}],
16486							[{translateX: 0}]
16487						]
16488					},
16489					/* Animate.css */
16490					"callout.flash": {
16491						defaultDuration: 1100,
16492						calls: [
16493							[{opacity: [0, "easeInOutQuad", 1]}],
16494							[{opacity: [1, "easeInOutQuad"]}],
16495							[{opacity: [0, "easeInOutQuad"]}],
16496							[{opacity: [1, "easeInOutQuad"]}]
16497						]
16498					},
16499					/* Animate.css */
16500					"callout.pulse": {
16501						defaultDuration: 825,
16502						calls: [
16503							[{scaleX: 1.1, scaleY: 1.1}, 0.50, {easing: "easeInExpo"}],
16504							[{scaleX: 1, scaleY: 1}, 0.50]
16505						]
16506					},
16507					/* Animate.css */
16508					"callout.swing": {
16509						defaultDuration: 950,
16510						calls: [
16511							[{rotateZ: 15}],
16512							[{rotateZ: -10}],
16513							[{rotateZ: 5}],
16514							[{rotateZ: -5}],
16515							[{rotateZ: 0}]
16516						]
16517					},
16518					/* Animate.css */
16519					"callout.tada": {
16520						defaultDuration: 1000,
16521						calls: [
16522							[{scaleX: 0.9, scaleY: 0.9, rotateZ: -3}, 0.10],
16523							[{scaleX: 1.1, scaleY: 1.1, rotateZ: 3}, 0.10],
16524							[{scaleX: 1.1, scaleY: 1.1, rotateZ: -3}, 0.10],
16525							["reverse", 0.125],
16526							["reverse", 0.125],
16527							["reverse", 0.125],
16528							["reverse", 0.125],
16529							["reverse", 0.125],
16530							[{scaleX: 1, scaleY: 1, rotateZ: 0}, 0.20]
16531						]
16532					},
16533					"transition.fadeIn": {
16534						defaultDuration: 500,
16535						calls: [
16536							[{opacity: [1, 0]}]
16537						]
16538					},
16539					"transition.fadeOut": {
16540						defaultDuration: 500,
16541						calls: [
16542							[{opacity: [0, 1]}]
16543						]
16544					},
16545					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16546					"transition.flipXIn": {
16547						defaultDuration: 700,
16548						calls: [
16549							[{opacity: [1, 0], transformPerspective: [800, 800], rotateY: [0, -55]}]
16550						],
16551						reset: {transformPerspective: 0}
16552					},
16553					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16554					"transition.flipXOut": {
16555						defaultDuration: 700,
16556						calls: [
16557							[{opacity: [0, 1], transformPerspective: [800, 800], rotateY: 55}]
16558						],
16559						reset: {transformPerspective: 0, rotateY: 0}
16560					},
16561					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16562					"transition.flipYIn": {
16563						defaultDuration: 800,
16564						calls: [
16565							[{opacity: [1, 0], transformPerspective: [800, 800], rotateX: [0, -45]}]
16566						],
16567						reset: {transformPerspective: 0}
16568					},
16569					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16570					"transition.flipYOut": {
16571						defaultDuration: 800,
16572						calls: [
16573							[{opacity: [0, 1], transformPerspective: [800, 800], rotateX: 25}]
16574						],
16575						reset: {transformPerspective: 0, rotateX: 0}
16576					},
16577					/* Animate.css */
16578					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16579					"transition.flipBounceXIn": {
16580						defaultDuration: 900,
16581						calls: [
16582							[{opacity: [0.725, 0], transformPerspective: [400, 400], rotateY: [-10, 90]}, 0.50],
16583							[{opacity: 0.80, rotateY: 10}, 0.25],
16584							[{opacity: 1, rotateY: 0}, 0.25]
16585						],
16586						reset: {transformPerspective: 0}
16587					},
16588					/* Animate.css */
16589					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16590					"transition.flipBounceXOut": {
16591						defaultDuration: 800,
16592						calls: [
16593							[{opacity: [0.9, 1], transformPerspective: [400, 400], rotateY: -10}],
16594							[{opacity: 0, rotateY: 90}]
16595						],
16596						reset: {transformPerspective: 0, rotateY: 0}
16597					},
16598					/* Animate.css */
16599					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16600					"transition.flipBounceYIn": {
16601						defaultDuration: 850,
16602						calls: [
16603							[{opacity: [0.725, 0], transformPerspective: [400, 400], rotateX: [-10, 90]}, 0.50],
16604							[{opacity: 0.80, rotateX: 10}, 0.25],
16605							[{opacity: 1, rotateX: 0}, 0.25]
16606						],
16607						reset: {transformPerspective: 0}
16608					},
16609					/* Animate.css */
16610					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16611					"transition.flipBounceYOut": {
16612						defaultDuration: 800,
16613						calls: [
16614							[{opacity: [0.9, 1], transformPerspective: [400, 400], rotateX: -15}],
16615							[{opacity: 0, rotateX: 90}]
16616						],
16617						reset: {transformPerspective: 0, rotateX: 0}
16618					},
16619					/* Magic.css */
16620					"transition.swoopIn": {
16621						defaultDuration: 850,
16622						calls: [
16623							[{opacity: [1, 0], transformOriginX: ["100%", "50%"], transformOriginY: ["100%", "100%"], scaleX: [1, 0], scaleY: [1, 0], translateX: [0, -700], translateZ: 0}]
16624						],
16625						reset: {transformOriginX: "50%", transformOriginY: "50%"}
16626					},
16627					/* Magic.css */
16628					"transition.swoopOut": {
16629						defaultDuration: 850,
16630						calls: [
16631							[{opacity: [0, 1], transformOriginX: ["50%", "100%"], transformOriginY: ["100%", "100%"], scaleX: 0, scaleY: 0, translateX: -700, translateZ: 0}]
16632						],
16633						reset: {transformOriginX: "50%", transformOriginY: "50%", scaleX: 1, scaleY: 1, translateX: 0}
16634					},
16635					/* Magic.css */
16636					/* Support: Loses rotation in IE9/Android 2.3. (Fades and scales only.) */
16637					"transition.whirlIn": {
16638						defaultDuration: 850,
16639						calls: [
16640							[{opacity: [1, 0], transformOriginX: ["50%", "50%"], transformOriginY: ["50%", "50%"], scaleX: [1, 0], scaleY: [1, 0], rotateY: [0, 160]}, 1, {easing: "easeInOutSine"}]
16641						]
16642					},
16643					/* Magic.css */
16644					/* Support: Loses rotation in IE9/Android 2.3. (Fades and scales only.) */
16645					"transition.whirlOut": {
16646						defaultDuration: 750,
16647						calls: [
16648							[{opacity: [0, "easeInOutQuint", 1], transformOriginX: ["50%", "50%"], transformOriginY: ["50%", "50%"], scaleX: 0, scaleY: 0, rotateY: 160}, 1, {easing: "swing"}]
16649						],
16650						reset: {scaleX: 1, scaleY: 1, rotateY: 0}
16651					},
16652					"transition.shrinkIn": {
16653						defaultDuration: 750,
16654						calls: [
16655							[{opacity: [1, 0], transformOriginX: ["50%", "50%"], transformOriginY: ["50%", "50%"], scaleX: [1, 1.5], scaleY: [1, 1.5], translateZ: 0}]
16656						]
16657					},
16658					"transition.shrinkOut": {
16659						defaultDuration: 600,
16660						calls: [
16661							[{opacity: [0, 1], transformOriginX: ["50%", "50%"], transformOriginY: ["50%", "50%"], scaleX: 1.3, scaleY: 1.3, translateZ: 0}]
16662						],
16663						reset: {scaleX: 1, scaleY: 1}
16664					},
16665					"transition.expandIn": {
16666						defaultDuration: 700,
16667						calls: [
16668							[{opacity: [1, 0], transformOriginX: ["50%", "50%"], transformOriginY: ["50%", "50%"], scaleX: [1, 0.625], scaleY: [1, 0.625], translateZ: 0}]
16669						]
16670					},
16671					"transition.expandOut": {
16672						defaultDuration: 700,
16673						calls: [
16674							[{opacity: [0, 1], transformOriginX: ["50%", "50%"], transformOriginY: ["50%", "50%"], scaleX: 0.5, scaleY: 0.5, translateZ: 0}]
16675						],
16676						reset: {scaleX: 1, scaleY: 1}
16677					},
16678					/* Animate.css */
16679					"transition.bounceIn": {
16680						defaultDuration: 800,
16681						calls: [
16682							[{opacity: [1, 0], scaleX: [1.05, 0.3], scaleY: [1.05, 0.3]}, 0.35],
16683							[{scaleX: 0.9, scaleY: 0.9, translateZ: 0}, 0.20],
16684							[{scaleX: 1, scaleY: 1}, 0.45]
16685						]
16686					},
16687					/* Animate.css */
16688					"transition.bounceOut": {
16689						defaultDuration: 800,
16690						calls: [
16691							[{scaleX: 0.95, scaleY: 0.95}, 0.35],
16692							[{scaleX: 1.1, scaleY: 1.1, translateZ: 0}, 0.35],
16693							[{opacity: [0, 1], scaleX: 0.3, scaleY: 0.3}, 0.30]
16694						],
16695						reset: {scaleX: 1, scaleY: 1}
16696					},
16697					/* Animate.css */
16698					"transition.bounceUpIn": {
16699						defaultDuration: 800,
16700						calls: [
16701							[{opacity: [1, 0], translateY: [-30, 1000]}, 0.60, {easing: "easeOutCirc"}],
16702							[{translateY: 10}, 0.20],
16703							[{translateY: 0}, 0.20]
16704						]
16705					},
16706					/* Animate.css */
16707					"transition.bounceUpOut": {
16708						defaultDuration: 1000,
16709						calls: [
16710							[{translateY: 20}, 0.20],
16711							[{opacity: [0, "easeInCirc", 1], translateY: -1000}, 0.80]
16712						],
16713						reset: {translateY: 0}
16714					},
16715					/* Animate.css */
16716					"transition.bounceDownIn": {
16717						defaultDuration: 800,
16718						calls: [
16719							[{opacity: [1, 0], translateY: [30, -1000]}, 0.60, {easing: "easeOutCirc"}],
16720							[{translateY: -10}, 0.20],
16721							[{translateY: 0}, 0.20]
16722						]
16723					},
16724					/* Animate.css */
16725					"transition.bounceDownOut": {
16726						defaultDuration: 1000,
16727						calls: [
16728							[{translateY: -20}, 0.20],
16729							[{opacity: [0, "easeInCirc", 1], translateY: 1000}, 0.80]
16730						],
16731						reset: {translateY: 0}
16732					},
16733					/* Animate.css */
16734					"transition.bounceLeftIn": {
16735						defaultDuration: 750,
16736						calls: [
16737							[{opacity: [1, 0], translateX: [30, -1250]}, 0.60, {easing: "easeOutCirc"}],
16738							[{translateX: -10}, 0.20],
16739							[{translateX: 0}, 0.20]
16740						]
16741					},
16742					/* Animate.css */
16743					"transition.bounceLeftOut": {
16744						defaultDuration: 750,
16745						calls: [
16746							[{translateX: 30}, 0.20],
16747							[{opacity: [0, "easeInCirc", 1], translateX: -1250}, 0.80]
16748						],
16749						reset: {translateX: 0}
16750					},
16751					/* Animate.css */
16752					"transition.bounceRightIn": {
16753						defaultDuration: 750,
16754						calls: [
16755							[{opacity: [1, 0], translateX: [-30, 1250]}, 0.60, {easing: "easeOutCirc"}],
16756							[{translateX: 10}, 0.20],
16757							[{translateX: 0}, 0.20]
16758						]
16759					},
16760					/* Animate.css */
16761					"transition.bounceRightOut": {
16762						defaultDuration: 750,
16763						calls: [
16764							[{translateX: -30}, 0.20],
16765							[{opacity: [0, "easeInCirc", 1], translateX: 1250}, 0.80]
16766						],
16767						reset: {translateX: 0}
16768					},
16769					"transition.slideUpIn": {
16770						defaultDuration: 900,
16771						calls: [
16772							[{opacity: [1, 0], translateY: [0, 20], translateZ: 0}]
16773						]
16774					},
16775					"transition.slideUpOut": {
16776						defaultDuration: 900,
16777						calls: [
16778							[{opacity: [0, 1], translateY: -20, translateZ: 0}]
16779						],
16780						reset: {translateY: 0}
16781					},
16782					"transition.slideDownIn": {
16783						defaultDuration: 900,
16784						calls: [
16785							[{opacity: [1, 0], translateY: [0, -20], translateZ: 0}]
16786						]
16787					},
16788					"transition.slideDownOut": {
16789						defaultDuration: 900,
16790						calls: [
16791							[{opacity: [0, 1], translateY: 20, translateZ: 0}]
16792						],
16793						reset: {translateY: 0}
16794					},
16795					"transition.slideLeftIn": {
16796						defaultDuration: 1000,
16797						calls: [
16798							[{opacity: [1, 0], translateX: [0, -20], translateZ: 0}]
16799						]
16800					},
16801					"transition.slideLeftOut": {
16802						defaultDuration: 1050,
16803						calls: [
16804							[{opacity: [0, 1], translateX: -20, translateZ: 0}]
16805						],
16806						reset: {translateX: 0}
16807					},
16808					"transition.slideRightIn": {
16809						defaultDuration: 1000,
16810						calls: [
16811							[{opacity: [1, 0], translateX: [0, 20], translateZ: 0}]
16812						]
16813					},
16814					"transition.slideRightOut": {
16815						defaultDuration: 1050,
16816						calls: [
16817							[{opacity: [0, 1], translateX: 20, translateZ: 0}]
16818						],
16819						reset: {translateX: 0}
16820					},
16821					"transition.slideUpBigIn": {
16822						defaultDuration: 850,
16823						calls: [
16824							[{opacity: [1, 0], translateY: [0, 75], translateZ: 0}]
16825						]
16826					},
16827					"transition.slideUpBigOut": {
16828						defaultDuration: 800,
16829						calls: [
16830							[{opacity: [0, 1], translateY: -75, translateZ: 0}]
16831						],
16832						reset: {translateY: 0}
16833					},
16834					"transition.slideDownBigIn": {
16835						defaultDuration: 850,
16836						calls: [
16837							[{opacity: [1, 0], translateY: [0, -75], translateZ: 0}]
16838						]
16839					},
16840					"transition.slideDownBigOut": {
16841						defaultDuration: 800,
16842						calls: [
16843							[{opacity: [0, 1], translateY: 75, translateZ: 0}]
16844						],
16845						reset: {translateY: 0}
16846					},
16847					"transition.slideLeftBigIn": {
16848						defaultDuration: 800,
16849						calls: [
16850							[{opacity: [1, 0], translateX: [0, -75], translateZ: 0}]
16851						]
16852					},
16853					"transition.slideLeftBigOut": {
16854						defaultDuration: 750,
16855						calls: [
16856							[{opacity: [0, 1], translateX: -75, translateZ: 0}]
16857						],
16858						reset: {translateX: 0}
16859					},
16860					"transition.slideRightBigIn": {
16861						defaultDuration: 800,
16862						calls: [
16863							[{opacity: [1, 0], translateX: [0, 75], translateZ: 0}]
16864						]
16865					},
16866					"transition.slideRightBigOut": {
16867						defaultDuration: 750,
16868						calls: [
16869							[{opacity: [0, 1], translateX: 75, translateZ: 0}]
16870						],
16871						reset: {translateX: 0}
16872					},
16873					/* Magic.css */
16874					"transition.perspectiveUpIn": {
16875						defaultDuration: 800,
16876						calls: [
16877							[{opacity: [1, 0], transformPerspective: [800, 800], transformOriginX: [0, 0], transformOriginY: ["100%", "100%"], rotateX: [0, -180]}]
16878						],
16879						reset: {transformPerspective: 0, transformOriginX: "50%", transformOriginY: "50%"}
16880					},
16881					/* Magic.css */
16882					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16883					"transition.perspectiveUpOut": {
16884						defaultDuration: 850,
16885						calls: [
16886							[{opacity: [0, 1], transformPerspective: [800, 800], transformOriginX: [0, 0], transformOriginY: ["100%", "100%"], rotateX: -180}]
16887						],
16888						reset: {transformPerspective: 0, transformOriginX: "50%", transformOriginY: "50%", rotateX: 0}
16889					},
16890					/* Magic.css */
16891					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16892					"transition.perspectiveDownIn": {
16893						defaultDuration: 800,
16894						calls: [
16895							[{opacity: [1, 0], transformPerspective: [800, 800], transformOriginX: [0, 0], transformOriginY: [0, 0], rotateX: [0, 180]}]
16896						],
16897						reset: {transformPerspective: 0, transformOriginX: "50%", transformOriginY: "50%"}
16898					},
16899					/* Magic.css */
16900					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16901					"transition.perspectiveDownOut": {
16902						defaultDuration: 850,
16903						calls: [
16904							[{opacity: [0, 1], transformPerspective: [800, 800], transformOriginX: [0, 0], transformOriginY: [0, 0], rotateX: 180}]
16905						],
16906						reset: {transformPerspective: 0, transformOriginX: "50%", transformOriginY: "50%", rotateX: 0}
16907					},
16908					/* Magic.css */
16909					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16910					"transition.perspectiveLeftIn": {
16911						defaultDuration: 950,
16912						calls: [
16913							[{opacity: [1, 0], transformPerspective: [2000, 2000], transformOriginX: [0, 0], transformOriginY: [0, 0], rotateY: [0, -180]}]
16914						],
16915						reset: {transformPerspective: 0, transformOriginX: "50%", transformOriginY: "50%"}
16916					},
16917					/* Magic.css */
16918					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16919					"transition.perspectiveLeftOut": {
16920						defaultDuration: 950,
16921						calls: [
16922							[{opacity: [0, 1], transformPerspective: [2000, 2000], transformOriginX: [0, 0], transformOriginY: [0, 0], rotateY: -180}]
16923						],
16924						reset: {transformPerspective: 0, transformOriginX: "50%", transformOriginY: "50%", rotateY: 0}
16925					},
16926					/* Magic.css */
16927					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16928					"transition.perspectiveRightIn": {
16929						defaultDuration: 950,
16930						calls: [
16931							[{opacity: [1, 0], transformPerspective: [2000, 2000], transformOriginX: ["100%", "100%"], transformOriginY: [0, 0], rotateY: [0, 180]}]
16932						],
16933						reset: {transformPerspective: 0, transformOriginX: "50%", transformOriginY: "50%"}
16934					},
16935					/* Magic.css */
16936					/* Support: Loses rotation in IE9/Android 2.3 (fades only). */
16937					"transition.perspectiveRightOut": {
16938						defaultDuration: 950,
16939						calls: [
16940							[{opacity: [0, 1], transformPerspective: [2000, 2000], transformOriginX: ["100%", "100%"], transformOriginY: [0, 0], rotateY: 180}]
16941						],
16942						reset: {transformPerspective: 0, transformOriginX: "50%", transformOriginY: "50%", rotateY: 0}
16943					}
16944				};
16945
16946		/* Register the packaged effects. */
16947		for (var effectName in Velocity.RegisterEffect.packagedEffects) {
16948			if (Velocity.RegisterEffect.packagedEffects.hasOwnProperty(effectName)) {
16949				Velocity.RegisterEffect(effectName, Velocity.RegisterEffect.packagedEffects[effectName]);
16950			}
16951		}
16952
16953		/*********************
16954		 Sequence Running
16955		 **********************/
16956
16957		/* Note: Sequence calls must use Velocity's single-object arguments syntax. */
16958		Velocity.RunSequence = function(originalSequence) {
16959			var sequence = $.extend(true, [], originalSequence);
16960
16961			if (sequence.length > 1) {
16962				$.each(sequence.reverse(), function(i, currentCall) {
16963					var nextCall = sequence[i + 1];
16964
16965					if (nextCall) {
16966						/* Parallel sequence calls (indicated via sequenceQueue:false) are triggered
16967						 in the previous call's begin callback. Otherwise, chained calls are normally triggered
16968						 in the previous call's complete callback. */
16969						var currentCallOptions = currentCall.o || currentCall.options,
16970								nextCallOptions = nextCall.o || nextCall.options;
16971
16972						var timing = (currentCallOptions && currentCallOptions.sequenceQueue === false) ? "begin" : "complete",
16973								callbackOriginal = nextCallOptions && nextCallOptions[timing],
16974								options = {};
16975
16976						options[timing] = function() {
16977							var nextCallElements = nextCall.e || nextCall.elements;
16978							var elements = nextCallElements.nodeType ? [nextCallElements] : nextCallElements;
16979
16980							if (callbackOriginal) {
16981								callbackOriginal.call(elements, elements);
16982							}
16983							Velocity(currentCall);
16984						};
16985
16986						if (nextCall.o) {
16987							nextCall.o = $.extend({}, nextCallOptions, options);
16988						} else {
16989							nextCall.options = $.extend({}, nextCallOptions, options);
16990						}
16991					}
16992				});
16993
16994				sequence.reverse();
16995			}
16996
16997			Velocity(sequence[0]);
16998		};
16999	}((window.jQuery || window.Zepto || window), window, (window ? window.document : undefined));
17000}));
17001
17002},{}]},{},[40]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.