├── .gitattributes
├── .gitignore
├── README.md
├── api.php
├── app
├── data
│ └── timeline.json
├── js
│ ├── dispatcher.js
│ ├── react-controls.js
│ ├── react-gmaps.js
│ ├── react-inputslider.js
│ ├── react-itemdetail.js
│ ├── react-itemlist.js
│ └── react-pagination.js
├── less
│ ├── compiled.css
│ ├── compiled.less
│ ├── lesshat.less
│ ├── size_0.less
│ ├── size_1024.less
│ ├── size_1024_1376.less
│ ├── size_1024_up.less
│ ├── size_1376.less
│ ├── size_1376_1840.less
│ ├── size_1376_up.less
│ ├── size_1840.less
│ ├── size_1840_up.less
│ ├── size_640.less
│ ├── size_640_800.less
│ ├── size_640_up.less
│ ├── size_800.less
│ ├── size_800_1024.less
│ ├── size_800_up.less
│ └── style.less
├── main.js
└── routes
│ └── core-routes.js
├── package.json
├── public
├── bundle.min.js
├── compiled.css
├── functions.js
├── imgs
│ ├── Smoke-Element.png
│ ├── logo.png
│ └── react-logo.svg
└── markerwithlabel.js
├── server.js
└── views
└── index.ejs
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Folder config file
2 | Desktop.ini
3 |
4 | # Recycle Bin used on file shares
5 | $RECYCLE.BIN/
6 | .DS_Store
7 |
8 | node_modules/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # History of Humanity
2 |
3 | A brief overview of what humanity has been up to since 1750, powered by React.JS and the Wikipedia API
4 |
5 | Demo @ https://wail.es/history-of-humanity/
6 |
7 | Prototype blog post @ https://builtvisible.com/building-content-in-react/
8 |
9 | Final result blog post @ https://wail.es/build-seo-friendly-universal-js-apps-reactjs/
10 |
11 | ## Notes
12 |
13 | Uses httpplease, classie and MarkerWithLabel. And React.js, obviously.
--------------------------------------------------------------------------------
/api.php:
--------------------------------------------------------------------------------
1 | 0)
67 | History.pushState(null, 'Page ' + page + ' | Modern History of Humanity', '/history-of-humanity/p/' + page);
68 | else
69 | History.pushState(null, 'Modern History of Humanity', '/history-of-humanity/');
70 | }
71 |
72 | updateItems(dateType, newDate, newTag) {
73 | var newState = {};
74 | var items = [];
75 | var n = 0;
76 |
77 | if (dateType === false) {
78 | var sDate = 1750;
79 | var eDate = 2015;
80 |
81 | newState.startDate = sDate;
82 | newState.endDate = eDate;
83 | }
84 | else {
85 | var sDate =(dateType === 'startDate') ? parseInt(newDate) : parseInt(this.state.startDate);
86 | var eDate =(dateType === 'endDate') ? parseInt(newDate) : parseInt(this.state.endDate);
87 | }
88 |
89 | for (var i = sDate; i <= eDate; i++) {
90 | var loopEnd =(isset(this.props.timeline[i])) ? this.props.timeline[i].length : 0;
91 |
92 | for (var j = 0; j < loopEnd; j++) {
93 | if ((newTag !== false && this.props.timeline[i][j].tags.indexOf(newTag) > -1) || newTag === false) {
94 | items[n] = this.props.timeline[i][j];
95 | items[n].year = i;
96 | items[n].position = j;
97 | n++;
98 | }
99 | }
100 | }
101 |
102 | if (this.state.pointer >= Math.floor(items.length / this.state.nRows))
103 | newState.pointer = Math.floor(items.length / this.state.nRows);
104 |
105 | newState.tag = newTag;
106 |
107 | newState.selectedItems = items;
108 | newState.nPages = Math.ceil(items.length / this.state.nRows);
109 |
110 | if (dateType !== false)
111 | newState[dateType] = newDate;
112 |
113 | this.setState(newState);
114 | }
115 |
116 | historyUpdate() {
117 | var parts = window.location.pathname.replace('/history-of-humanity/', '').split('/');
118 |
119 | if (String(window.location.pathname).match(/\/history-of-humanity\/\d+\/\d+\/.+/i) !== null) {
120 | this.setItemDetail({"target": {"dataset": { "year": parts[0], "position": parts[1] }}}, false);
121 | }
122 | else {
123 | this.hideItemDetail({"target": {"id": "hohContainer"}}, false);
124 | }
125 | }
126 |
127 | setItemDetail(e, updateHistory) {
128 | if (typeof e.preventDefault === 'function')
129 | e.preventDefault();
130 |
131 | if (isset(e.target.dataset.year))
132 | var year = e.target.dataset.year;
133 | else if (isset(e.target.parentNode.dataset.year))
134 | var year = e.target.parentNode.dataset.year;
135 | else if (isset(e.target.parentNode.parentNode.dataset.year))
136 | var year = e.target.parentNode.parentNode.dataset.year;
137 |
138 | if (isset(e.target.dataset.position))
139 | var position = e.target.dataset.position;
140 | else if (isset(e.target.parentNode.dataset.position))
141 | var position = e.target.parentNode.dataset.position;
142 | else if (isset(e.target.parentNode.parentNode.dataset.position))
143 | var position = e.target.parentNode.parentNode.dataset.position;
144 |
145 | var itemData = this.props.timeline[year][position];
146 |
147 | if (isset(itemData.links.main))
148 | {
149 | var wikiTitle = itemData.links.main.link.replace('//en.wikipedia.org/wiki/', '');
150 | this.setWikiData(wikiTitle);
151 | }
152 | else {
153 | this.setState({ wikiData: false, wikiImages: false })
154 | }
155 |
156 | this.setState({ itemDetail: itemData });
157 |
158 | if (!isset(updateHistory) || updateHistory !== false)
159 | History.pushState(null, itemData.text + ' | Modern History of Humanity', '/history-of-humanity/' + year + '/' + position + '/' + wikiTitle);
160 | }
161 |
162 | hideItemDetail(e, updateHistory) {
163 | if (e.target.id === 'hohContainer' || e.target.id === 'hideItemDetail' || e.target.parentNode.id === 'hideItemDetail') {
164 | this.setState({ itemDetail: false });
165 |
166 | var n = parseInt(this.state.pointer) + 1;
167 |
168 | if (!isset(updateHistory) || updateHistory !== false) {
169 | if (this.state.pointer === 0)
170 | History.pushState(null, 'Modern History of Humanity', '/history-of-humanity/');
171 | else
172 | History.pushState(null, 'Page ' + n + ' | Modern History of Humanity', '/history-of-humanity/p/' + n);
173 | }
174 | }
175 | }
176 |
177 | setWikiData(wikiTitle) {
178 | var self = this;
179 | var wikiApiLink = 'https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|images&exintro=&explaintext=&titles=' + wikiTitle;
180 | var wikidata = axios.get('https://wail.es/history/api.php?url=' + encodeURIComponent(wikiApiLink.replace(/&/g, "&")))
181 |
182 | wikidata.then(function(res) {
183 | var newState = { wikiData: false, wikiImages: false };
184 |
185 | if (isset(res.data.query.pages)) {
186 | var pageId = Object.keys(res.data.query.pages);
187 |
188 | newState.wikiData = res.data.query.pages[pageId],
189 | newState.wikiImages = [];
190 |
191 | if (isset(newState.wikiData.images)) {
192 | for (var i = newState.wikiData.images.length - 1; i >= 0; i--) {
193 | var title = newState.wikiData.images[i].title.replace('File:', '').replace(/\s+/g,"_");
194 |
195 | if (title.indexOf('.jpg') === -1 && title.indexOf('.png') === -1 && i === 0)
196 | newState.wikiData.images.splice(i, 1);
197 | else if (title.indexOf('.jpg') === -1 && title.indexOf('.png') === -1) {
198 | newState.wikiData.images.splice(i, 1);
199 | continue;
200 | }
201 |
202 | var imgLink = 'https://en.wikipedia.org/w/api.php?action=query&titles=Image:' + title + '&prop=imageinfo&iiprop=url&format=json';
203 | var wikiImgs = axios.get('https://wail.es/history/api.php?url=' + encodeURIComponent(imgLink.replace(/&/g, "&")));
204 |
205 | if (i === 0) {
206 | wikiImgs.then(function(imgRes) {
207 | if (isset(imgRes.data.query.pages['-1']) && isset(imgRes.data.query.pages['-1'].imageinfo))
208 | newState.wikiImages.push(imgRes.data.query.pages['-1'].imageinfo[0].url);
209 |
210 | self.setState(newState);
211 | })
212 | .catch(function(e) {
213 | console.log('error in xhr 2');
214 | console.log(e);
215 | });
216 | }
217 | else {
218 | wikiImgs.then(function(imgRes) {
219 | if (isset(imgRes.data.query.pages['-1']) && isset(imgRes.data.query.pages['-1'].imageinfo))
220 | newState.wikiImages.push(imgRes.data.query.pages['-1'].imageinfo[0].url);
221 | })
222 | .catch(function(e) {
223 | console.log('error in xhr 3');
224 | console.log(e);
225 | });
226 | }
227 | }
228 | }
229 | else
230 | self.setState(newState);
231 | }
232 | })
233 | .catch(function(e) {
234 | console.log('error in xhr 1');
235 | console.log(e);
236 | });
237 | }
238 |
239 | updateDate(e) {
240 | if (!isNaN(e.x)) {
241 | var year = Math.floor(e.x);
242 |
243 | if (e.name === 'startDate' && year !== this.state.startDate)
244 | this.updateItems('startDate', year, this.state.tag);
245 | else if (e.name === 'endDate' && year !== this.state.endDate)
246 | this.updateItems('endDate', year, this.state.tag);
247 | }
248 | }
249 |
250 | updatePointer(e) {
251 | var update = true;
252 |
253 | if (isset(e.target.parentNode.dataset.pointer))
254 | var pointer = e.target.parentNode.dataset.pointer;
255 | else if (isset(e.target.dataset.pointer))
256 | var pointer = e.target.dataset.pointer;
257 |
258 | if (pointer === '1' &&(this.state.pointer + 1 < Math.floor(this.state.selectedItems.length / this.state.nRows)))
259 | var newPointer = this.state.pointer + 1
260 | else if (pointer === '1' &&(this.state.pointer + 1 >= Math.floor(this.state.selectedItems.length / this.state.nRows)))
261 | update = false;
262 | else if (pointer === '0' && this.state.pointer > 0)
263 | var newPointer = this.state.pointer - 1;
264 | else
265 | var newPointer = 0;
266 |
267 | if (update) {
268 | this.setState({ pointer: newPointer });
269 |
270 | if (newPointer === 0)
271 | History.pushState(null, 'Modern History of Humanity', '/history-of-humanity/');
272 | else
273 | History.pushState(null, 'Modern History of Humanity', '/history-of-humanity/p/' + newPointer);
274 | }
275 | }
276 |
277 | handleMarkerClick(e) { this.setState({ highlightLatLong: e }) }
278 |
279 | updateTag(e) {
280 | e.preventDefault();
281 |
282 | var newVal = e.target.dataset.value;
283 |
284 | if (newVal === '')
285 | newVal = false;
286 |
287 | this.updateItems('endDate', this.state.endDate, newVal);
288 | }
289 |
290 | renderItemDetail() {
291 | var checkPropsAgainstUrl = true;
292 |
293 | if (typeof window !== 'undefined') {
294 | var parts = window.location.pathname.replace('/history-of-humanity/', '').split('/');
295 |
296 | checkPropsAgainstUrl =(isset(this.props.initparams)
297 | && this.props.initparams.year === parts[0]
298 | && this.props.initparams.position === parts[1]
299 | && this.props.initparams.name === parts[2]);
300 | }
301 |
302 | var itemDetail = false,
303 | wikiData = false,
304 | wikiImages = false;
305 |
306 | if (this.state.itemDetail !== false)
307 | var itemDetail = this.state.itemDetail;
308 | else if (isset(this.props.initwikidata) && isset(this.props.initwikidata.itemDetail) && checkPropsAgainstUrl)
309 | var itemDetail = this.props.initwikidata.itemDetail;
310 |
311 | if (this.state.wikiData !== false)
312 | var wikiData = this.state.wikiData;
313 | else if (isset(this.props.initwikidata) && isset(this.props.initwikidata.wikiData) && checkPropsAgainstUrl)
314 | var wikiData = this.props.initwikidata.wikiData;
315 |
316 | if (this.state.wikiImages !== false)
317 | var wikiImages = this.state.wikiImages;
318 | else if (isset(this.props.initwikidata) && isset(this.props.initwikidata.wikiImages) && checkPropsAgainstUrl)
319 | var wikiImages = this.props.initwikidata.wikiImages;
320 |
321 | if (itemDetail !== false) {
322 | return (
323 | React.createElement("div", { key: "itemDetailContainer" },
324 | React.createElement(ReactCSSTransitionGroup, {
325 | id: 'hideItemDetail',
326 | transitionName: 'itemDetailTransition',
327 | transitionAppear: true,
328 | transitionAppearTimeout: 500,
329 | transitionEnterTimeout: 500,
330 | transitionLeaveTimeout: 500,
331 | onClick: this.hideItemDetail
332 | },
333 | React.createElement("i", { className: 'fa fa-times' })
334 | ),
335 | React.createElement(ItemDetail, {
336 | itemDetail: itemDetail,
337 | wikiData: wikiData,
338 | wikiImages: wikiImages
339 | })
340 | )
341 | )
342 | }
343 | else
344 | return [];
345 | }
346 |
347 | render() {
348 | var highchartKey = this.state.startDate.toString() + this.state.endDate.toString();
349 | var mapsKey = this.state.startDate.toString() + this.state.endDate.toString() + this.state.tag + this.state.pointer;
350 |
351 | var itemDetail =(this.state.itemDetail !== false || isset(this.props.initwikidata))
352 | ? this.renderItemDetail()
353 | : [];
354 |
355 | return (
356 | React.createElement("div", {
357 | id: "hohContainer",
358 | onClick: this.hideItemDetail
359 | },
360 | React.createElement("div", { id: "mapAndControls" },
361 | React.createElement(GMap, {
362 | initialZoom: 3,
363 | centerLat: 30,
364 | centerLng: 30,
365 | mapsKey: mapsKey,
366 | items: this.state.selectedItems,
367 | pointer: this.state.pointer,
368 | handleMarkerClick: this.handleMarkerClick,
369 | show: this.state.nRows
370 | }),
371 | React.createElement(Controls, {
372 | startDate: this.state.startDate,
373 | endDate: this.state.endDate,
374 | tag: this.state.tag,
375 | inputHandler: this.updateDate,
376 | tagHandler: this.updateTag,
377 | buttonHandler: this.updatePointer
378 | })
379 | ),
380 | React.createElement(ItemList, {
381 | items: this.state.selectedItems,
382 | highlightLatLong: this.state.highlightLatLong,
383 | pointer: this.state.pointer,
384 | show: this.state.nRows,
385 | itemHandler: this.setItemDetail
386 | }),
387 | itemDetail,
388 | React.createElement(Pagination, {
389 | nPages: this.state.nPages,
390 | maxBlocks: "11",
391 | clickHandler: this.handlePaginatorClicked,
392 | pointer: this.state.pointer
393 | })
394 | )
395 | );
396 | }
397 | }
--------------------------------------------------------------------------------
/app/js/react-controls.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import InputSlider from './react-inputslider.js';
3 |
4 | export default class Controls extends React.Component {
5 | constructor() {
6 | super();
7 |
8 | this.tags = [
9 | { value: '', title: 'All' },
10 | { value: 'art', title: 'Art' },
11 | { value: 'cold war', title: 'Cold War' },
12 | { value: 'conflict', title: 'Conflict' },
13 | { value: 'crime', title: 'Crime' },
14 | { value: 'death', title: 'Death' },
15 | { value: 'disaster', title: 'Disaster' },
16 | { value: 'ecology', title: 'Ecology' },
17 | { value: 'economy', title: 'Economy' },
18 | { value: 'equality', title: 'Equality' },
19 | { value: 'exploration', title: 'Exploration' },
20 | { value: 'government', title: 'Government' },
21 | { value: 'history', title: 'History' },
22 | { value: 'internal conflict', title: 'Internal Conflict' },
23 | { value: 'natural disaster', title: 'Natural Disaster' },
24 | { value: 'person', title: 'Person' },
25 | { value: 'religion', title: 'Religion' },
26 | { value: 'science', title: 'Science' },
27 | { value: 'social', title: 'Social' },
28 | { value: 'space', title: 'Space' },
29 | { value: 'sport', title: 'Sport' },
30 | { value: 'technology', title: 'Technology' },
31 | { value: 'terrorism', title: 'Terrorism' },
32 | { value: 'toys', title: 'Toys' },
33 | { value: 'transport', title: 'Transport' },
34 | { value: 'treaty', title: 'Treaty' },
35 | { value: 'world population', title: 'World Population' },
36 | { value: 'ww1', title: 'WW1' },
37 | { value: 'ww2', title: 'WW2' }
38 | ];
39 |
40 | this.toggleTags = this.toggleTags.bind(this);
41 | this.hideTags = this.hideTags.bind(this);
42 | this.tagHandler = this.tagHandler.bind(this);
43 | this.renderTag = this.renderTag.bind(this);
44 |
45 | this.state = { showTags: false };
46 | }
47 |
48 | toggleTags() { this.setState({ showTags: !this.state.showTags }) }
49 | hideTags() { this.setState({ showTags: false }) }
50 |
51 | tagHandler(e) {
52 | this.hideTags();
53 | this.props.tagHandler(e);
54 | }
55 |
56 | renderTag(tag) { return React.createElement("li", { key: tag.value, 'data-value': tag.value, onClick: this.tagHandler }, tag.title) }
57 |
58 | render() {
59 | var tags = [];
60 | var currentTag = 'All';
61 |
62 | for (var i = this.tags.length - 1; i >= 0; i--) {
63 | if (this.state.showTags)
64 | tags[i] = this.renderTag(this.tags[i]);
65 |
66 | if (this.props.tag === this.tags[i].value)
67 | currentTag = this.tags[i].title;
68 | }
69 |
70 | var listClass = 'dropdown';
71 |
72 | if (this.state.showTags)
73 | listClass += ' active';
74 |
75 | return (
76 | React.createElement("div", { id: "controls" },
77 | React.createElement("div", { className: "panel" },
78 | React.createElement("label", { htmlFor: 'startDate' }, 'Start Date'),
79 | React.createElement("div", { className: 'yearPanel' }, this.props.startDate),
80 | React.createElement(InputSlider, {
81 | axis: 'x',
82 | x: this.props.startDate,
83 | xMin: 1750,
84 | xMax: 2014,
85 | name: 'startDate',
86 | onChange: this.props.inputHandler
87 | })
88 | ),
89 | React.createElement("div", { className: "panel" },
90 | React.createElement("label", { htmlFor: 'endDate' }, 'End Date'),
91 | React.createElement("div", { className: 'yearPanel' }, this.props.endDate),
92 | React.createElement(InputSlider, {
93 | axis: 'x',
94 | x: this.props.endDate,
95 | xMin: 1751,
96 | xMax: 2015,
97 | name: 'endDate',
98 | onChange: this.props.inputHandler
99 | })
100 | ),
101 | React.createElement("div", { className: "panel" },
102 | React.createElement("label", null, 'Tag'),
103 | React.createElement("p", { id: 'tagHandler', onClick: this.toggleTags }, currentTag),
104 | React.createElement("ul", { id: 'tags', className: listClass }, tags)
105 | ),
106 | React.createElement("span", { className: 'fa_button', id: 'backButton', 'data-pointer': 0, onClick: this.props.buttonHandler },
107 | React.createElement("i", { className: 'fa fa-angle-double-left' })
108 | ),
109 | React.createElement("span", { className: 'fa_button', id: 'forwardButton', 'data-pointer': 1, onClick: this.props.buttonHandler },
110 | React.createElement("i", { className: 'fa fa-angle-double-right' })
111 | )
112 | )
113 | )
114 | }
115 | }
--------------------------------------------------------------------------------
/app/js/react-gmaps.js:
--------------------------------------------------------------------------------
1 | function isset (obj) { return typeof obj !== 'undefined'; }
2 |
3 | import React from 'react';
4 |
5 | class GMap extends React.Component {
6 | constructor() {
7 | super();
8 |
9 | // load initial map
10 | this.markers = [];
11 | this.latlongs = [];
12 |
13 | this.componentDidMount = this.componentDidMount.bind(this);
14 | this.componentWillUnmount = this.componentWillUnmount.bind(this);
15 | this.shouldComponentUpdate = this.shouldComponentUpdate.bind(this);
16 | this.componentDidUpdate = this.componentDidUpdate.bind(this);
17 | this.updateDimensions = this.updateDimensions.bind(this);
18 | this.clearMarkers = this.clearMarkers.bind(this);
19 | this.createMarkers = this.createMarkers.bind(this);
20 | this.setMapOnAll = this.setMapOnAll.bind(this);
21 | this.createMap = this.createMap.bind(this);
22 | this.checkBounds = this.checkBounds.bind(this);
23 | }
24 |
25 | componentDidMount(props) {
26 | var self = this;
27 |
28 | if (typeof google === 'object') {
29 | this.map = this.createMap();
30 |
31 | google.maps.event.addListener(this.map, 'center_changed', function() {
32 | self.checkBounds(self.map);
33 | });
34 |
35 | google.maps.event.addDomListener(window, "resize", function() {
36 | var center = self.map.getCenter();
37 | google.maps.event.trigger(self.map, "resize");
38 | self.map.setCenter(center);
39 | });
40 |
41 | if (this.props.items.length > 0)
42 | this.createMarkers();
43 |
44 | window.addEventListener("resize", this.updateDimensions);
45 | }
46 |
47 | this.updateDimensions();
48 | }
49 |
50 | componentWillUnmount() { if (typeof window !== 'undefined') window.removeEventListener("resize", this.updateDimensions) }
51 |
52 | shouldComponentUpdate(newProps, newState) {
53 | return newProps.mapsKey !== this.props.mapsKey
54 | ||(this.state !== null && isset(this.state.width) && isset(newState.width) && newState.width !== this.state.width)
55 | }
56 |
57 | componentDidUpdate() {
58 | if (typeof google === 'object') {
59 | this.clearMarkers();
60 | this.createMarkers();
61 | }
62 | }
63 |
64 | updateDimensions(returnStyles) {
65 | if (typeof window !== 'undefined') {
66 | var dims = getViewportSize();
67 |
68 | var styles = {
69 | height: '600px',
70 | width: '1300px'
71 | }
72 |
73 | if (dims.width < 640) {
74 | styles.height = '250px';
75 | styles.width = '285px';
76 | }
77 | else if (dims.width > 640 && dims.width < 800) {
78 | styles.height = '325px';
79 | styles.width = '425px';
80 | }
81 | else if (dims.width > 800 && dims.width < 1024) {
82 | styles.height = '455px';
83 | styles.width = '625px';
84 | }
85 | else if (dims.width > 1024 && dims.width < 1376) {
86 | styles.width = '900px';
87 | }
88 | else if (dims.width > 1376 && dims.width < 1840) {
89 | styles.width = '1200px';
90 | }
91 |
92 | this.setState(styles);
93 | }
94 | }
95 |
96 | clearMarkers() {
97 | this.setMapOnAll(null);
98 | this.markers = [];
99 | this.latlongs = [];
100 | }
101 |
102 | createMarkers() {
103 | var x = this.props.pointer * this.props.show;
104 | var y = this.props.pointer * this.props.show + this.props.show;
105 | var year = this.props.items[x].year;
106 |
107 | for (var i = x; i < y; i++) {
108 | var currentItem = this.props.items[i];
109 |
110 | if (isset(currentItem.latlong) && currentItem.latlong.length > 0)
111 | {
112 | for (var j = currentItem.latlong.length - 1; j >= 0; j--) {
113 | var marker = new MarkerWithLabel({
114 | icon: {
115 | path: google.maps.SymbolPath.CIRCLE,
116 | scale: 0,
117 | },
118 | labelAnchor: new google.maps.Point(10, 10),
119 | labelClass: "label",
120 | position: new google.maps.LatLng(currentItem.latlong[j][0], currentItem.latlong[j][1]),
121 | map: this.map
122 | });
123 |
124 | this.markers.push(marker);
125 | this.latlongs.push(currentItem.latlong[j]);
126 | }
127 | }
128 | }
129 |
130 | this.setMapOnAll(this.map);
131 | }
132 |
133 | setMapOnAll(map) {
134 | var self = this;
135 |
136 | for (var i = 0; i < this.markers.length; i++) {
137 | this.markers[i].setMap(map);
138 | google.maps.event.addListener(this.markers[i], "click", function(e) {
139 | self.props.handleMarkerClick({
140 | lat: this.position.lat().toFixed(1),
141 | long: this.position.lng().toFixed(1)
142 | })
143 | })
144 | }
145 | }
146 |
147 | createMap() {
148 | var mapOptions = {
149 | //disableDefaultUI: true,
150 | maxZoom: 10,
151 | minZoom: 2,
152 | scrollwheel: false,
153 | mapTypeId: google.maps.MapTypeId.ROADMAP,
154 | styles: this.style,
155 | streetViewControl: !1,
156 | mapTypeControl: !1,
157 | zoom: this.props.initialZoom,
158 | center: new google.maps.LatLng(this.props.centerLat, this.props.centerLng)
159 | }
160 |
161 | return new google.maps.Map(this.refs.mapCanvas, mapOptions)
162 | }
163 |
164 | // If the map position is out of range, move it back
165 | checkBounds(map) {
166 | var latNorth = map.getBounds().getNorthEast().lat();
167 | var latSouth = map.getBounds().getSouthWest().lat();
168 | var newLat;
169 |
170 | var pi = Math.PI;
171 |
172 | var t1 = Math.pow(Math.E, pi);
173 | var t2 = Math.pow(Math.E, 0 - pi);
174 | var sinh =(t1 - t2) / 2;
175 |
176 | var atan = Math.atan(sinh);
177 |
178 | var pos = atan * 180 / pi;
179 | var neg = 0 - pos;
180 |
181 | if (latNorth < pos && latSouth > neg) /* in both side -> it's ok */
182 | return;
183 | else {
184 | if (latNorth > pos && latSouth < neg) /* out both side -> it's ok */
185 | return;
186 | else {
187 | if (latNorth > pos)
188 | newLat = map.getCenter().lat() -(latNorth - pos); /* too north, centering */
189 | if (latSouth < neg)
190 | newLat = map.getCenter().lat() -(latSouth + 85); /* too south, centering */
191 | }
192 | }
193 |
194 | if (newLat) {
195 | var newCenter = new google.maps.LatLng(newLat, map.getCenter().lng());
196 | map.setCenter(newCenter);
197 | }
198 | }
199 |
200 | render() {
201 | return (
202 | React.createElement("div", { id: "gmap" },
203 | React.createElement("div", { ref: "mapCanvas", id: "mapCanvas" })
204 | )
205 | )
206 | }
207 | }
208 |
209 | GMap.prototype.style = [{
210 | "featureType": "landscape",
211 | "elementType": "geometry.fill",
212 | "stylers": [{
213 | "visibility": "on"
214 | }, {
215 | "color": "#DDD4CB"
216 | }]
217 | }, {
218 | "featureType": "poi",
219 | "stylers": [{
220 | "visibility": "off"
221 | }]
222 | }, {
223 | "featureType": "road",
224 | "stylers": [{
225 | "visibility": "off"
226 | }]
227 | }, {
228 | "featureType": "transit",
229 | "stylers": [{
230 | "visibility": "off"
231 | }]
232 | }, {
233 | "featureType": "administrative",
234 | "elementType": "labels",
235 | "stylers": [{
236 | "color": "#808080"
237 | }, {
238 | "visibility": "on"
239 | }, {
240 | "weight": 0.2
241 | }]
242 | }, {
243 | "featureType": "administrative.locality",
244 | "stylers": [{
245 | "visibility": "off"
246 | }]
247 | }, {
248 | "featureType": "administrative.neighborhood",
249 | "stylers": [{
250 | "visibility": "off"
251 | }]
252 | }, {
253 | "featureType": "administrative.land_parcel",
254 | "stylers": [{
255 | "visibility": "off"
256 | }]
257 | }, {
258 | "featureType": "administrative.country",
259 | "elementType": "labels.text.fill",
260 | "stylers": [{
261 | "invert_lightness": true
262 | }, {
263 | "visibility": "simplified"
264 | }]
265 | }, {
266 | "featureType": "administrative.country",
267 | "elementType": "geometry.stroke",
268 | "stylers": [{
269 | "color": "#F7F5F2"
270 | }, {
271 | "visibility": "on"
272 | }, {
273 | "weight": 1.0
274 | }]
275 | }, {
276 | "featureType": "administrative.province",
277 | "stylers": [{
278 | "visibility": "off"
279 | }]
280 | }, {
281 | "featureType": "water",
282 | "elementType": "geometry.fill",
283 | "stylers": [{
284 | "color": "#F7F5F2"
285 | }, {
286 | "visibility": "on"
287 | }]
288 | }, {
289 | "featureType": "water",
290 | "elementType": "labels.text.fill",
291 | "stylers": [{
292 | "visibility": "simplified"
293 | }, {
294 | "invert_lightness": true
295 | }]
296 | }, {
297 | "elementType": "labels.text.fill",
298 | "stylers": [{
299 | "color": "#808080"
300 | }]
301 | }];
302 |
303 | export default GMap;
--------------------------------------------------------------------------------
/app/js/react-inputslider.js:
--------------------------------------------------------------------------------
1 | // based on //raw.githubusercontent.com/wangzuo/react-input-slider/gh-pages/dist/input-slider.js
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 |
5 | export default class InputSlider extends React.Component {
6 | constructor() {
7 | super();
8 |
9 | this.getPosition = this.getPosition.bind(this);
10 | this.handleSliderClick = this.handleSliderClick.bind(this);
11 | this.handleMoveStart = this.handleMoveStart.bind(this);
12 | this.handleDrag = this.handleDrag.bind(this);
13 | this.handleDragEnd = this.handleDragEnd.bind(this);
14 | this.handleClick = this.handleClick.bind(this);
15 | this.getPos = this.getPos.bind(this);
16 | this.changeValue = this.changeValue.bind(this);
17 |
18 | this.state = { mobile:(typeof window !== 'undefined') ? mobileCheck() : false };
19 | }
20 |
21 | getPosition() {
22 | if (this.props.axis !== 'x') {
23 | var top = (this.props.y - this.props.yMin) /(this.props.yMax - this.props.yMin) * 100;
24 |
25 | if (top > 100) top = 100;
26 | if (top < 0) top = 0;
27 | }
28 | else
29 | var top = 0;
30 |
31 | if (this.props.axis !== 'y') {
32 | var left = (this.props.x - this.props.xMin) /(this.props.xMax - this.props.xMin) * 100;
33 |
34 | if (left > 100) left = 100;
35 | if (left < 0) left = 0;
36 | }
37 | else
38 | var left = 0;
39 |
40 | return { top: top + '%', left: left + '%' };
41 | }
42 |
43 | handleSliderClick(e) {
44 | e.stopPropagation();
45 | e.nativeEvent.stopImmediatePropagation();
46 | }
47 |
48 | handleMoveStart(e) {
49 | e.preventDefault();
50 | var dom = this.refs.handle.getDOMNode();
51 |
52 | this.start = {
53 | x: dom.offsetLeft,
54 | y: dom.offsetTop
55 | };
56 |
57 | this.offset = {
58 | x: e.clientX,
59 | y: e.clientY
60 | };
61 |
62 | if (!this.state.mobile) {
63 | document.addEventListener('mousemove', this.handleDrag);
64 | document.addEventListener('mouseup', this.handleDragEnd);
65 | }
66 | else {
67 | document.addEventListener('touchmove', this.handleDrag);
68 | document.addEventListener('touchend', this.handleDragEnd);
69 | }
70 | }
71 |
72 | handleDrag(e) {
73 | e.preventDefault();
74 | this.changeValue(this.getPos(e));
75 | }
76 |
77 | handleDragEnd(e) {
78 | e.preventDefault();
79 |
80 | if (!this.state.mobile) {
81 | document.removeEventListener('mousemove', this.handleDrag);
82 | document.removeEventListener('mouseup', this.handleDragEnd);
83 | }
84 | else {
85 | document.removeEventListener('touchmove', this.handleDrag);
86 | document.removeEventListener('touchend', this.handleDragEnd);
87 | }
88 |
89 | if (this.props.onDragEnd) this.changeValue(this.getPos(e), true);
90 | }
91 |
92 | handleClick(e) {
93 | var rect = this.refs[this.props.name].getBoundingClientRect();
94 |
95 | this.changeValue({
96 | left: e.clientX - rect.left,
97 | top: e.clientY - rect.top
98 | }, true);
99 | }
100 |
101 | getPos(e) {
102 | if (!this.state.mobile) {
103 | var posX = e.clientX + this.start.x - this.offset.x;
104 | var posY = e.clientY + this.start.y - this.offset.y;
105 | }
106 | else {
107 | var posX = e.changedTouches[0].screenX - e.changedTouches[0].radiusX;
108 | var posY = e.changedTouches[0].screenY - e.changedTouches[0].radiusY;
109 | }
110 |
111 | return {
112 | left: posX,
113 | top: posY
114 | };
115 | }
116 |
117 | changeValue(pos, dragEnd) {
118 | if (!this.props.onChange) return;
119 |
120 | var rect = this.refs[this.props.name].getBoundingClientRect();
121 | var width = rect.width;
122 | var height = rect.height;
123 | var left = pos.left;
124 | var top = pos.top;
125 | var axis = this.props.axis;
126 |
127 | if (left < 0) left = 0;
128 | if (left > width) left = width;
129 | if (top < 0) top = 0;
130 | if (top > height) top = height;
131 |
132 | var x = 0;
133 | var y = 0;
134 | if (axis === 'x' || axis === 'xy') {
135 | x = left / width *(this.props.xMax - this.props.xMin) + this.props.xMin;
136 | }
137 | if (axis === 'y' || axis === 'xy') {
138 | y = top / height *(this.props.yMax - this.props.yMin) + this.props.yMin;
139 | }
140 |
141 | this.props.onChange({ x: x, y: y, name: this.props.name });
142 |
143 | if (this.props.onDragEnd && dragEnd) this.props.onDragEnd({ x: x, y: y, name: this.props.name });
144 | }
145 |
146 | render() {
147 | var pos = this.getPosition();
148 | var axis = this.props.axis;
149 | var valueStyle = {};
150 |
151 | if (axis === 'x') valueStyle.width = pos.left;
152 | if (axis === 'y') valueStyle.height = pos.top;
153 |
154 | return (
155 | React.createElement("div", { className: 'slider slider_' + axis, id: this.props.name, ref: this.props.name, onClick: this.handleClick, onTouchStart: this.handleClick },
156 | React.createElement('div', { className: 'value', style: valueStyle }),
157 | React.createElement('div', { className: 'handle', ref: 'handle', onMouseDown: this.handleMoveStart, onTouchStart: this.handleMoveStart, onClick: this.handleSliderClick, style: pos })
158 | )
159 | )
160 | }
161 | }
--------------------------------------------------------------------------------
/app/js/react-itemdetail.js:
--------------------------------------------------------------------------------
1 | function isset (obj) { return typeof obj !== 'undefined'; }
2 |
3 | import React from 'react';
4 | import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
5 |
6 | export default class ItemDetail extends React.Component {
7 | constructor() {
8 | super();
9 |
10 | this.componentWillReceiveProps = this.componentWillReceiveProps.bind(this);
11 | this.renderRelatedLink = this.renderRelatedLink.bind(this);
12 | this.noRelatedLinks = this.noRelatedLinks.bind(this);
13 | this.renderItemLocation = this.renderItemLocation.bind(this);
14 | this.noLocations = this.noLocations.bind(this);
15 | this.renderGalleryImg = this.renderGalleryImg.bind(this);
16 | this.noImages = this.noImages.bind(this);
17 | this.renderMainLink = this.renderMainLink.bind(this);
18 | this.renderControls = this.renderControls.bind(this);
19 | this.buttonHandler = this.buttonHandler.bind(this);
20 | this.renderExtract = this.renderExtract.bind(this);
21 |
22 | this.state = {
23 | galleryPointer: 0,
24 | maxHeight: 600
25 | };
26 | }
27 |
28 | componentDidMount() {
29 | if (typeof window !== 'undefined')
30 | this.setState({ maxHeight: getViewportSize().height - 20 })
31 | }
32 |
33 | componentWillReceiveProps() { this.setState({ galleryPointer: 0 }); }
34 |
35 | renderRelatedLink(link) {
36 | return (
37 | React.createElement("li", { key: 'relatedLink' + link.link },
38 | React.createElement("a", { href: link.link, target: '_blank' }, link.title)
39 | )
40 | )
41 | }
42 |
43 | noRelatedLinks() { return React.createElement("li", { key: 'relatedLink' }, 'No related links') }
44 |
45 | renderItemLocation(location) { return React.createElement("li", { key: 'loc' + location }, location) }
46 | noLocations() { return React.createElement("li", { key: 'locations' }, 'No locations to show') }
47 |
48 | renderGalleryImg(imgUrl) { return React.createElement("img", { key: 'img' + imgUrl, className: 'galleryImg', src: imgUrl }) }
49 | noImages() { return React.createElement("p", { key: 'gallery' }, 'No images') }
50 |
51 | renderMainLink() {
52 | if (isset(this.props.itemDetail.links.main)) {
53 | return (
54 | React.createElement("p", { key: 'mainLink', id: 'mainLink' },
55 | React.createElement("span", null, 'Full article: '),
56 | React.createElement("a", { href: this.props.itemDetail.links.main.link, target: '_blank' }, this.props.itemDetail.links.main.title)
57 | )
58 | )
59 | }
60 | else
61 | return []
62 | }
63 |
64 | renderControls() {
65 | return (
66 | React.createElement("div", { key: 'galleryControls' },
67 | React.createElement("span", { className: 'fa_button', id: 'galleryBack', onClick: this.buttonHandler },
68 | React.createElement("i", { className: 'fa fa-angle-double-left' })
69 | ),
70 | React.createElement("span", { className: 'fa_button', id: 'galleryForward', onClick: this.buttonHandler },
71 | React.createElement("i", { className: 'fa fa-angle-double-right' })
72 | )
73 | )
74 | )
75 | }
76 |
77 | buttonHandler(e) {
78 | var id = (isset(e.target.id) &&(e.target.id === 'galleryBack' || e.target.id === 'galleryForward')) ? e.target.id : e.target.parentNode.id;
79 |
80 | if (id === 'galleryForward')
81 | var newPointerPosition =(this.state.galleryPointer + 3 < this.props.wikiImages.length) ? this.state.galleryPointer + 1 : false;
82 | else
83 | var newPointerPosition =(this.state.galleryPointer - 1 < 0) ? false : this.state.galleryPointer - 1;
84 |
85 | if (newPointerPosition)
86 | this.setState({ galleryPointer: newPointerPosition });
87 | }
88 |
89 | renderExtract(extract, i) { return React.createElement("p", { key: 'extracts_' + i }, extract) }
90 |
91 | render() {
92 | if (this.props.itemDetail !== false) {
93 | if (isset(this.props.itemDetail.links.related))
94 | var itemLinks = this.props.itemDetail.links.related.map(this.renderRelatedLink);
95 | else
96 | var itemLinks = this.noRelatedLinks();
97 |
98 | if (isset(this.props.itemDetail.locations[0]))
99 | var itemLocations = this.props.itemDetail.locations.map(this.renderItemLocation);
100 | else
101 | var itemLocations = this.noLocations();
102 |
103 | var mainLink = this.renderMainLink();
104 |
105 | if (this.props.wikiImages !== false && this.props.wikiImages.length > 0) {
106 | var gallery = [];
107 | var n =(this.state.galleryPointer + 3 <= this.props.wikiImages.length) ? this.state.galleryPointer + 3 : this.props.wikiImages.length;
108 |
109 | for (var i = this.state.galleryPointer; i < n; i++) {
110 | var img = this.renderGalleryImg(this.props.wikiImages[i]);
111 | gallery.push(img);
112 | }
113 | }
114 | else
115 | var gallery = this.noImages();
116 |
117 | if (this.props.wikiData !== false && this.props.wikiData.extract !== false && this.props.wikiData.extract !== '') {
118 | var paragraphs = this.props.wikiData.extract.split("\n");
119 | var extract = paragraphs.map(this.renderExtract);
120 | }
121 | else
122 | extract = [];
123 |
124 | var controls =(gallery.length > 0) ? this.renderControls() : [];
125 |
126 | return (
127 | React.createElement(ReactCSSTransitionGroup, { id: "itemDetail", transitionName: 'itemDetailTransition', transitionAppear: true, transitionAppearTimeout: 500, transitionEnterTimeout: 500, transitionLeaveTimeout: 500, style: { maxHeight: this.state.maxHeight } },
128 | React.createElement("h3", null, this.props.itemDetail.text),
129 | React.createElement("div", null,
130 | extract,
131 | mainLink
132 | ),
133 | React.createElement("h4", null, 'Locations'),
134 | React.createElement("ul", null, itemLocations),
135 | React.createElement("h4", null, 'Related Links'),
136 | React.createElement("ul", null, itemLinks),
137 | React.createElement("div", { id: 'galleryTitle' },
138 | React.createElement("h4", null, 'Images'),
139 | controls
140 | ),
141 | React.createElement("div", { id: 'gallery' }, gallery)
142 | )
143 | )
144 | }
145 | }
146 | }
--------------------------------------------------------------------------------
/app/js/react-itemlist.js:
--------------------------------------------------------------------------------
1 | function isset (obj) { return typeof obj !== 'undefined'; }
2 |
3 | import React from 'react';
4 |
5 | export default class ItemList extends React.Component {
6 | constructor() {
7 | super();
8 |
9 | this.componentDidMount = this.componentDidMount.bind(this);
10 | this.componentWillReceiveProps = this.componentWillReceiveProps.bind(this);
11 | this.scrollAnimate = this.scrollAnimate.bind(this);
12 | this.renderYear = this.renderYear.bind(this);
13 | this.renderItemThumbnail = this.renderItemThumbnail.bind(this);
14 | this.renderItem = this.renderItem.bind(this);
15 | this.itemHandler = this.itemHandler.bind(this);
16 | this.renderItems = this.renderItems.bind(this);
17 | this.loadingItems = this.loadingItems.bind(this);
18 | this.noItems = this.noItems.bind(this);
19 |
20 | this.state = { jumpTo: false };
21 | }
22 |
23 | componentDidMount() { this.jumping = false }
24 |
25 | componentWillReceiveProps(nextProps) {
26 | if (this.props.highlightLatLong === false && nextProps.highlightLatLong !== false || this.props.highlightLatLong.lat !== nextProps.highlightLatLong.lat)
27 | this.setState({ jumpTo: false });
28 | }
29 |
30 | //gist.github.com/dezinezync/5487119
31 | scrollAnimate(Y, duration) {
32 | var start = Date.now(),
33 | elem = document.documentElement.scrollTop ? document.documentElement : document.body,
34 | from = elem.scrollTop;
35 |
36 | if (from === Y)
37 | return; // Prevent scrolling to the Y point if already there
38 |
39 | function min(a,b) { return a < b ? a : b; }
40 |
41 | function scroll(timestamp) {
42 | var currentTime = Date.now(),
43 | t = min(1,((currentTime - start) / duration)),
44 | easedT = t < .5 ? 2 * t * t : -1 +(4 - 2 * t) * t;
45 |
46 | elem.scrollTop = (easedT *(Y - from)) + from;
47 |
48 | if (t < 1)
49 | requestAnimationFrame(scroll);
50 | }
51 |
52 | requestAnimationFrame(scroll)
53 | }
54 |
55 | renderYear(x, y, year) { return React.createElement("li", { key: 'year' + x + y + year, className: 'yearTitle' }, year) }
56 |
57 | renderItemThumbnail(item, key) {
58 | var picKey = 'thumb' + key;
59 |
60 | return (isset(item.thumbnail) && item.thumbnail !== '')
61 | ? React.createElement("img", { key: picKey, className: 'thumbnail', src: item.thumbnail })
62 | : [];
63 | }
64 |
65 | renderItem(item, i) {
66 | var key = 0, i, chr, len;
67 |
68 | for (i = 0, len = item.text.length; i < len; i++) {
69 | chr = item.text.charCodeAt(i);
70 | key =((key << 5) - key) + chr;
71 | key |= 0; // Convert to 32bit integer
72 | }
73 |
74 | var itemThumbnail = this.renderItemThumbnail(item, key);
75 | var className = 'itemPanel';
76 |
77 | var testPropLatLongSet = isset(this.props.highlightLatLong) && isset(this.props.highlightLatLong.lat) && isset(this.props.highlightLatLong.long);
78 | var testItemLatLongSet = isset(item.latlong) && isset(item.latlong[0]) && isset(item.latlong[0][0]);
79 |
80 | if (testPropLatLongSet && testItemLatLongSet) {
81 | var latFixed = item.latlong[0][0].toFixed(1);
82 | var longFixed = item.latlong[0][1].toFixed(1);
83 |
84 | if (latFixed === this.props.highlightLatLong.lat && longFixed === this.props.highlightLatLong.long) {
85 | className += ' highlightMap';
86 |
87 | if (this.state.jumpTo === false && this.jumping === false) {
88 | this.jumping = true;
89 | this.scrollAnimate($(key).offsetTop, 1000);
90 | }
91 | }
92 | }
93 |
94 | if (parseInt(this.state.jumpTo) === parseInt(key))
95 | className += ' highlightClick';
96 |
97 |
98 | var title =(isset(item.links) && isset(item.links.main) && isset(item.links.main.link)) ? item.links.main.link.replace('//en.wikipedia.org/wiki/', '') : '';
99 |
100 | return (
101 | React.createElement("li", { key: key, id: key, 'data-year': item.year, 'data-position': item.position, className: className, onClick: this.itemHandler },
102 | itemThumbnail,
103 | React.createElement("p", null,
104 | React.createElement("a", { href: '/history-of-humanity/' + item.year + '/' + item.position + '/' + title }, item.text)
105 | ),
106 | React.createElement("div", { className: 'readmore' },
107 | React.createElement("span", { 'data-year': item.year, 'data-position': item.position }, 'Read more...')
108 | )
109 | )
110 | )
111 | }
112 |
113 | itemHandler(e) {
114 | if (isset(e.target.id) && e.target.id !== '')
115 | var newJumpTo = e.target.id;
116 | else if (isset(e.target.parentNode.id) && e.target.parentNode.id !== '')
117 | var newJumpTo = e.target.parentNode.id;
118 | else if (isset(e.target.parentNode.parentNode.id) && e.target.parentNode.parentNode.id !== '')
119 | var newJumpTo = e.target.parentNode.parentNode.id;
120 |
121 | if (this.state.jumpTo === false || parseInt(this.state.jumpTo) !== parseInt(newJumpTo)) {
122 | this.scrollAnimate($(newJumpTo).offsetTop, 1000);
123 | this.setState({ jumpTo: newJumpTo });
124 | }
125 |
126 | this.props.itemHandler(e);
127 | }
128 |
129 | renderItems(item) {
130 | var relevantItems = [];
131 |
132 | if (this.props.items.length > 0)
133 | {
134 | var x = this.props.pointer * this.props.show;
135 | var y = this.props.pointer * this.props.show + this.props.show;
136 | var year = this.props.items[x].year;
137 |
138 | relevantItems.push(this.renderYear(x, y, this.props.items[x].year));
139 |
140 | for (var i = x; i < y; i++) {
141 | if (isset(this.props.items[i])) {
142 | if (this.props.items[i].year !== year) {
143 | relevantItems.push(this.renderYear(i, y, this.props.items[i].year));
144 | year = this.props.items[i].year;
145 | }
146 |
147 | relevantItems.push(this.renderItem(this.props.items[i], i));
148 | }
149 | }
150 | }
151 | this.jumping = false;
152 |
153 | return relevantItems;
154 | }
155 |
156 | loadingItems() { return React.createElement("li", { className: 'yearTitle' }, 'Loading data') }
157 | noItems() { return React.createElement("li", { className: 'yearTitle' }, 'No data for your selection') }
158 |
159 | render() {
160 | if (this.props.items === false)
161 | var itemsList = this.loadingItems()
162 | else if (this.props.items.length > 0)
163 | var itemsList = this.renderItems();
164 | else
165 | var itemsList = this.noItems();
166 |
167 | return (
168 | React.createElement("div", { id: "items" },
169 | React.createElement("ul", null,
170 | itemsList
171 | )
172 | )
173 | )
174 | }
175 | }
--------------------------------------------------------------------------------
/app/js/react-pagination.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class Pagination extends React.Component {
4 | constructor() {
5 | super();
6 |
7 | this.clickHandler = this.clickHandler.bind(this);
8 | this.updateArr = this.updateArr.bind(this);
9 | this.renderPaginationItems = this.renderPaginationItems.bind(this);
10 | this.renderNoPagination = this.renderNoPagination.bind(this);
11 | }
12 |
13 | clickHandler(e) {
14 | e.preventDefault();
15 |
16 | if (typeof e.target.dataset.pointer !== 'undefined')
17 | this.props.clickHandler(parseInt(e.target.dataset.pointer));
18 | else
19 | this.props.clickHandler(parseInt(e.target.parentNode.dataset.pointer));
20 | }
21 |
22 | updateArr() {
23 | var arr = [];
24 |
25 | if (this.props.maxBlocks - this.props.nPages < 2) {
26 | var maxPivotPages = Math.round((this.props.maxBlocks - 5) / 2);
27 | var minPage = Math.max(0, this.props.pointer - maxPivotPages);
28 | var maxPage = Math.min(this.props.nPages - 1, this.props.pointer + maxPivotPages * 2 -(this.props.pointer - minPage));
29 | var minPage = Math.max(0, minPage - (maxPivotPages * 2 -(maxPage - minPage)));
30 |
31 | var elipses = true;
32 | }
33 | else {
34 | var minPage = 0;
35 | var maxPage = this.props.nPages - 1;
36 |
37 | var elipses = false;
38 | }
39 |
40 | if (elipses && minPage !== 0) {
41 | arr[0] = 'prev';
42 | arr[1] = 'hellip1';
43 | }
44 |
45 | for(var i = minPage; i <= maxPage; i++) {
46 | arr.push(i);
47 | }
48 |
49 | if (elipses && this.props.nPages !== maxPage + 1) {
50 | arr.push('hellip2');
51 | arr.push('next');
52 | }
53 |
54 | return arr;
55 | }
56 |
57 | renderPaginationItems(i) {
58 | var selectedClass =(this.props.pointer === i) ? "selected clickable" : "clickable";
59 |
60 | if (i === 'prev') {
61 | return (
62 | React.createElement("li", { key: i, className: selectedClass, 'data-pointer': 0, onClick: this.clickHandler },
63 | React.createElement("a", { href: '/history-of-humanity/' }, '1')
64 | )
65 | )
66 | }
67 | else if (i === 'next') {
68 | return (
69 | React.createElement("li", { key: i, className: selectedClass, 'data-pointer': this.props.nPages - 1, onClick: this.clickHandler },
70 | React.createElement("a", { href: '/history-of-humanity/p/' + this.props.nPages }, this.props.nPages)
71 | )
72 | )
73 | }
74 | else if (i === 'hellip1' || i === 'hellip2')
75 | return React.createElement("li", { key: i, className: "more" }, "...")
76 | else {
77 | var n = i + 1;
78 | return React.createElement("li", { key: i, className: selectedClass, 'data-pointer': i, onClick: this.clickHandler },
79 | React.createElement("a", { href: '/history-of-humanity/p/' + n }, n)
80 | );
81 | }
82 | }
83 |
84 | renderNoPagination() { return React.createElement("li", { className: 'no_more' }, "No other pages") }
85 |
86 | render() {
87 | var className = 'paginator on';
88 |
89 | if (this.props.nPages > 1) {
90 | var arr = this.updateArr();
91 | var pagination = arr.map(this.renderPaginationItems)
92 | }
93 | else if (this.props.nPages === 0)
94 | var pagination = this.renderNoPagination();
95 | else {
96 | var pagination = [];
97 | className = 'paginator';
98 | }
99 |
100 | return React.createElement("ul", { className: className }, pagination)
101 | }
102 | }
--------------------------------------------------------------------------------
/app/less/compiled.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Open DAWS - Open Source Digital Application Wireframing Styleshee* Version 6.0.0
3 | * Collated by Pete Wailes - pete@watson-wail.es / @petewailes
4 | *
5 | * Includes elements from &| inspired by:
6 | *
7 | * * normalize.css by Nicolas Gallagher and Jonathan Neal - http://necolas.github.com/normalize.css/
8 | * * Foundation by Zurb - http://foundation.zurb.com/
9 | * * FramelessGrid by Joni Korpi - http://framelessgrid.com/
10 | * * Baseline CSS by Stéphane Curzi - http://baselinecss.com/
11 | * * LESSHat by CSS Hat - http://lesshat.com/
12 | */
13 |
14 | /*
15 | Common Mixins
16 | */
17 |
18 | @import "lesshat.less";
19 |
20 | /* Boot up LessHat */
21 |
22 | @font-size: 16; // Base font-size (pixels)
23 | @line-height: 26; // Base font-size (pixels)
24 | @font-line-ratio: 1.6; // Ratio of line height to font size
25 |
26 | @em: @font-size*1em; // Shorthand for outputting ems, e.g. "16/@em"
27 |
28 | @radius: 5px; // Default radius for borders
29 |
30 | @gutter: @line-height; // Gutter-width of your grid (pixels)
31 | @column: 48; // Column-width of your grid (pixels) -- gutter * 1.61803399 rounded up
32 | @column-and-gutter: @column + @gutter;
33 |
34 |
35 | /*
36 | Grid rules & column-widths in variables, in ems
37 | */
38 |
39 | .od-clearfix () {
40 | &:before, &:after {
41 | content: " ";
42 | display: table;
43 | }
44 | &:after { clear: both; }
45 | }
46 |
47 | .od-row () {
48 | .od-clearfix();
49 | display: block;
50 | margin: 0 auto;
51 | padding: 0;
52 | *zoom: 1;
53 |
54 | .row {
55 | width: auto;
56 |
57 | &.collapse { margin: 0; }
58 | }
59 | }
60 |
61 | .od-col () {
62 | float: left;
63 | min-height: 1px;
64 | position: relative;
65 | }
66 |
67 | .od-col-inverse () {
68 | float: right;
69 | min-height: 1px;
70 | position: relative;
71 | }
72 |
73 | .od-gutter () { margin: (@gutter / 2) * 1px; }
74 | .od-gutter-horizontal () {
75 | margin-left: (@gutter / 2) * 1px;
76 | margin-right: (@gutter / 2) * 1px;
77 | }
78 | .od-gutter-vertical () {
79 | margin-top: (@gutter / 2) * 1px;
80 | margin-bottom: (@gutter / 2) * 1px;
81 | }
82 | .od-gutter-top () { margin-top: @gutter * 1px; }
83 | .od-gutter-right () { margin-right: @gutter * 1px; }
84 | .od-gutter-bottom () { margin-bottom: @gutter * 1px; }
85 | .od-gutter-left () { margin-left: @gutter * 1px; }
86 |
87 | .od-internal-gutter () { padding: (@gutter / 2) * 1px; }
88 | .od-internal-gutter-horizontal () {
89 | padding-left: (@gutter / 2) * 1px;
90 | padding-right: (@gutter / 2) * 1px;
91 | }
92 | .od-internal-gutter-vertical () {
93 | padding-top: (@gutter / 2) * 1px;
94 | padding-bottom: (@gutter / 2) * 1px;
95 | }
96 | .od-internal-gutter-top () { padding-top: @gutter * 1px; }
97 | .od-internal-gutter-right () { padding-right: @gutter * 1px; }
98 | .od-internal-gutter-bottom () { padding-bottom: @gutter * 1px; }
99 | .od-internal-gutter-left () { padding-left: @gutter * 1px; }
100 |
101 | @1cols: ( 1 * @column-and-gutter - @gutter) * 1px; @1col: @1cols;
102 | @2cols: ( 2 * @column-and-gutter - @gutter) * 1px;
103 | @3cols: ( 3 * @column-and-gutter - @gutter) * 1px;
104 | @4cols: ( 4 * @column-and-gutter - @gutter) * 1px;
105 | @5cols: ( 5 * @column-and-gutter - @gutter) * 1px;
106 | @6cols: ( 6 * @column-and-gutter - @gutter) * 1px;
107 | @7cols: ( 7 * @column-and-gutter - @gutter) * 1px;
108 | @8cols: ( 8 * @column-and-gutter - @gutter) * 1px;
109 | @9cols: ( 9 * @column-and-gutter - @gutter) * 1px;
110 | @10cols: (10 * @column-and-gutter - @gutter) * 1px;
111 | @11cols: (11 * @column-and-gutter - @gutter) * 1px;
112 | @12cols: (12 * @column-and-gutter - @gutter) * 1px;
113 | @13cols: (13 * @column-and-gutter - @gutter) * 1px;
114 | @14cols: (14 * @column-and-gutter - @gutter) * 1px;
115 | @15cols: (15 * @column-and-gutter - @gutter) * 1px;
116 | @16cols: (16 * @column-and-gutter - @gutter) * 1px;
117 | @17cols: (17 * @column-and-gutter - @gutter) * 1px;
118 | @18cols: (18 * @column-and-gutter - @gutter) * 1px;
119 | @19cols: (19 * @column-and-gutter - @gutter) * 1px;
120 | @20cols: (20 * @column-and-gutter - @gutter) * 1px;
121 | @21cols: (21 * @column-and-gutter - @gutter) * 1px;
122 |
123 | .od-width-1 () { width: 8.33333%; }
124 | .od-width-2 () { width: 16.66667%; }
125 | .od-width-3 () { width: 25%; }
126 | .od-width-4 () { width: 33.33333%; }
127 | .od-width-5 () { width: 41.66667%; }
128 | .od-width-6 () { width: 50%; }
129 | .od-width-7 () { width: 58.33333%; }
130 | .od-width-8 () { width: 66.66667%; }
131 | .od-width-9 () { width: 75%; }
132 | .od-width-10 () { width: 83.33333%; }
133 | .od-width-11 () { width: 91.66667%; }
134 | .od-width-12 () { width: 100%; }
135 | .od-width-13 () { width: 108.33333%; }
136 | .od-width-14 () { width: 116.66667%; }
137 | .od-width-15 () { width: 125%; }
138 | .od-width-16 () { width: 133.33333%; }
139 | .od-width-17 () { width: 141.66667%; }
140 | .od-width-18 () { width: 150%; }
141 | .od-width-19 () { width: 158.33333%; }
142 | .od-width-20 () { width: 166.66667%; }
143 | .od-width-21 () { width: 175%; }
144 | .od-width-22 () { width: 183.33333%; }
145 | .od-width-23 () { width: 191.66667%; }
146 | .od-width-24 () { width: 200%; }
147 |
148 |
149 | // Column-widths in a function, in ems
150 | .od-width (@cols: 1) { width: (@cols * @column-and-gutter) * 1px; }
151 | .od-width-mod (@cols: 1, @decrease: 0, @increase: 0) { width: (@cols * @column-and-gutter - (@decrease * @em) + (@increase * @em)) * 1px; }
152 |
153 | .od-max-width (@cols: 1) { max-width: (@cols * @column-and-gutter) * 1px; }
154 | .od-max-width-mod (@cols: 1, @decrease: 0, @increase: 0) { max-width: (@cols * @column-and-gutter - (@decrease * @em) + (@increase * @em)) * 1px; }
155 |
156 | .od-height (@cols: 1) { height: (@cols * @column-and-gutter) * 1px; }
157 | .od-height-mod (@cols: 1, @decrease: 0, @increase: 0) { height: (@cols * @column-and-gutter - (@decrease * @em) + (@increase * @em)) * 1px; }
158 |
159 | .od-max-height (@cols: 1) { max-height: (@cols * @column-and-gutter) * 1px; }
160 | .od-max-height-mod (@cols: 1, @decrease: 0, @increase: 0) { max-height: (@cols * @column-and-gutter - (@decrease * @em) + (@increase * @em)) * 1px; }
161 |
162 | .od-push-col-gutter (@cols: 1) { margin-left: (@cols * @column-and-gutter) * 1px; }
163 | .od-push-col (@cols: 1) { margin-left: (@cols * @column-and-gutter) * 1px; }
164 |
165 | .od-top-positive (@cols: 1) { top: (@cols * @column-and-gutter) * 1px; }
166 | .od-top-negative (@cols: 1) { top: (0 - (@cols * @column-and-gutter)) * 1px; }
167 |
168 | .od-right-positive (@cols: 1) { right: (@cols * @column-and-gutter) * 1px; }
169 | .od-right-negative (@cols: 1) { right: (0 - (@cols * @column-and-gutter)) * 1px; }
170 |
171 | .od-bottom-positive (@cols: 1) { bottom: (@cols * @column-and-gutter) * 1px; }
172 | .od-bottom-negative (@cols: 1) { bottom: (0 - (@cols * @column-and-gutter)) * 1px; }
173 |
174 | .od-left-positive (@cols: 1) { left: (@cols * @column-and-gutter) * 1px; }
175 | .od-left-negative (@cols: 1) { left: (0 - (@cols * @column-and-gutter)) * 1px; }
176 |
177 | .od-clear { clear: both; }
178 |
179 | /*
180 | Resets & normalisation
181 | */
182 |
183 | html, body, div, span, a, img, h1, h2, h3, h4, h5, h6,
184 | hgroup, p, dl, dialog, dt, dd, ol, ul, li, abbr, acronym,
185 | address, b, big, blockquote, cite, code,
186 | del, dfn, em, i, ins, kbd, pre, q, samp, tt, var,
187 | small, strong, sub, sup, object, iframe,
188 | form, fieldset, label, legend, table, caption,
189 | tbody, tfoot, thead, tr, th, td,
190 | article, aside, footer, header, nav, section,
191 | figure, menu, time, mark, audio, video {
192 | background: transparent;
193 | border: 0;
194 | font-family: inherit;
195 | font-size: 100%;
196 | font-weight: inherit;
197 | font-style: inherit;
198 | margin: 0;
199 | outline: 0;
200 | padding: 0;
201 | text-align: left;
202 | vertical-align: baseline;
203 | white-space: normal;
204 | }
205 |
206 | article, aside, footer, header, nav, section, dialog, figure, hgroup, menu {
207 | display: block;
208 | }
209 |
210 | * { .box-sizing(border-box); }
211 |
212 | /* Deprecated and obsolete elements */
213 | applet, basefont, dir, font, isindex, menu, s, strike, u {
214 | border: 0;
215 | color: inherit;
216 | font-family: inherit;
217 | font-size: 100%;
218 | font-weight: normal;
219 | font-style: normal;
220 | margin: 0;
221 | outline: 0;
222 | padding: 0;
223 | text-decoration: inherit;
224 | text-align: left;
225 | vertical-align: baseline;
226 | white-space: normal;
227 | }
228 |
229 | dir, menu { list-style: none; }
230 | nobr { white-space: normal; }
231 | blink { text-decoration: none; }
232 | marquee { overflow: visible; }
233 |
234 | html { // Prevent iOS text size adjust after orientation change, without disabling user zoom
235 | font-family: sans-serif;
236 | height: 100%;
237 | -webkit-text-size-adjust: 100%;
238 | -ms-text-size-adjust: 100%;
239 | }
240 |
241 | body {
242 | background: white;
243 | color: #313131;
244 | font-size: 100%;
245 | line-height: 1.5;
246 | min-height: 100%;
247 | -webkit-tap-highlight-color: rgba(255,0,0, 0.62);
248 | }
249 |
250 |
251 | cite, dfn, em, i { font-style: italic; }
252 |
253 | mark { background: rgba(255, 255, 0, 0.4); padding: 0 .25em; }
254 |
255 | article, aside, details, figcaption, header, hgroup, nav, figure, section, footer { display: block; } /* Correct 'block' display not defined in IE 8/9 */
256 |
257 | audio, canvas, video { display: inline-block; } /* Correct 'inline-block' display not defined in IE 8/9 */
258 | audio:not([controls]) {
259 | display: none;
260 | height: 0;
261 | }
262 |
263 | /* For debugging */
264 |
265 | .test { background: #edd; }
266 |
267 |
268 | /*
269 | Typography
270 | */
271 |
272 | h1 { // 60px / 72px
273 | font-size: 3.75em;
274 | line-height: 1.2em;
275 | margin-bottom: 0.4em
276 | }
277 |
278 | h2 { // 48px / 48px
279 | font-size: 3em;
280 | line-height: 1em;
281 | margin-bottom: 0.5em
282 | }
283 |
284 | h3 { // 36px / 48px
285 | font-size: 2.25em;
286 | line-height: 1.3333333333333333333333333333333em;
287 | margin-bottom: 0.6667em
288 | }
289 |
290 | h4 { // 24px / 24px
291 | font-size: 1.5em;
292 | line-height: 1em;
293 | margin-bottom: 1em
294 | }
295 |
296 | h5 { // 21px / 24px
297 | font-size: 1.3125em;
298 | line-height: 1.1428571428571428571428571428571em;
299 | margin-bottom: 1.1428571428571428571428571428571em
300 | }
301 |
302 | h6 { // 18px / 24px
303 | font-size: 1.125em;
304 | line-height: 1.3333333333333333333333333333333em;
305 | margin-bottom: 1.3333333333333333333333333333333em
306 | }
307 |
308 | p, ul, ol, dl, dialog, blockquote, pre, code, address, td, th, label { // 16px / 24px
309 | display: block;
310 | font-size: 1em;
311 | line-height: @font-line-ratio * 1em;
312 | margin-bottom: @font-line-ratio * 1em;
313 | }
314 |
315 | small, p.small { // 14px / 24px
316 | font-size: 80%;
317 | line-height: 1.2;
318 | margin: 0;
319 | }
320 |
321 | a {
322 | color: #0049cc;
323 | text-decoration: none;
324 | &:hover { color: #0bcdd9; }
325 | &:focus { outline: thin dotted } /* Fix outline inconsistency between Chrome and other browsers */
326 | &:hover, &:active { outline: none } /* Better outline suppression */
327 | }
328 |
329 | a img, img {
330 | -ms-interpolation-mode: bicubic;
331 | border: 0;
332 | text-decoration: none;
333 | }
334 |
335 | hr {
336 | margin: 0 0 1.375em;
337 | padding: 0;
338 | }
339 |
340 | /* Addresses styles set to 'bolder' in Firefox 4+, Safari 5, and Chrome, enforces defaults for other browsers */
341 | b, strong, caption, th, thead, dt, legend { font-weight: 700; }
342 |
343 | /* Addresses styling not present in Safari 5 and Chrome, enforces defaults for other browsers */
344 | dfn, em, i { font-style: italic }
345 | var, address { font-style: normal }
346 |
347 | /* Code */
348 | p code, p pre, p var { line-height: @font-line-ratio * 1em * 0.75; }
349 |
350 | pre { // Allow line wrapping of 'pre'
351 | white-space: pre;
352 | white-space: pre-wrap;
353 | word-wrap: break-word
354 | }
355 |
356 | /* Lists */
357 | ol, ul, dl, dialog {
358 | list-style: none;
359 | list-style-position: inside;
360 | margin-left: @font-line-ratio * 1em;
361 | padding: 0
362 | }
363 |
364 | ul { list-style: disc outside; }
365 | ol { list-style: decimal outside; }
366 |
367 | li {
368 | font-size: 1em;
369 | margin-bottom: 1em;
370 |
371 | &:last-child,
372 | label { margin-bottom: 0; }
373 |
374 | ul, ol { margin: 1em @font-line-ratio * 1em 0; }
375 | ul { list-style-type: circle; }
376 | ol { list-style-type: lower-alpha; }
377 | }
378 |
379 | dl dd { margin-left: @font-line-ratio * 1em }
380 |
381 | nav ul li { margin-left: 0; }
382 |
383 | // Unstyled lists
384 |
385 | .od-unstyled-list () {
386 | list-style-type: none;
387 | margin-left: 0;
388 |
389 | li {
390 | display: block;
391 | list-style: none;
392 | }
393 | }
394 |
395 | .unstyled-list {
396 | .od-unstyled-list();
397 | padding: 0;
398 | }
399 |
400 | // Inline lists
401 |
402 | .od-inline () {
403 | .od-unstyled-list ();
404 | overflow: hidden;
405 |
406 | &:before, &:after {
407 | content: "";
408 | display: table;
409 | }
410 |
411 | &:after { clear: both; }
412 |
413 | li {
414 | display: inline-block;
415 | margin: 0;
416 |
417 | &:before {
418 | content: ""; // this can be altered for seperators. See below
419 | margin: 0 0.66667em;
420 | position: relative;
421 | top: 1px;
422 | }
423 | &:first-child:before { margin: 0; }
424 |
425 | form, input { margin-bottom: 0; }
426 | }
427 | }
428 |
429 | .inline {
430 | .od-inline();
431 | padding: 0;
432 |
433 | &.breadcrumbs li:before { content: "/"; }
434 | &.breadcrumbs li&:first-child:before {
435 | content: "";
436 | margin: 0;
437 | }
438 |
439 | &.no-margin li:before { margin: 0; }
440 | &.li-margin li {
441 | margin-left: 0.66667em;
442 |
443 | &:first-child { margin: 0; }
444 | &:before { margin: 0; }
445 | }
446 |
447 | .radius > *:first-child,
448 | .radius > *:first-child > a,
449 | .radius > *:first-child > button,
450 | .radius > *:first-child > .button {
451 | .border-bottom-left-radius(@radius);
452 | .border-top-left-radius(@radius);
453 | }
454 |
455 | .radius > *:last-child,
456 | .radius > *:last-child > a,
457 | .radius > *:last-child > button,
458 | .radius > *:last-child > .button {
459 | .border-bottom-right-radius(@radius);
460 | .border-top-right-radius(@radius);
461 | }
462 | }
463 |
464 | .inline-scroll {
465 | .od-inline();
466 | padding: 0;
467 | overflow-x: auto;
468 | white-space: nowrap;
469 | }
470 |
471 | .pagination {
472 | .od-inline();
473 | padding: 0;
474 |
475 | li {
476 | margin-left: 0.25em;
477 |
478 | &:hover a {
479 | background: #eee;
480 | }
481 |
482 | a {
483 | .border-radius(@radius);
484 | .transition(background-color 300ms ease-out);
485 | display: block;
486 | padding: 0.1em 0.75rem 0.1em;
487 |
488 | &.selected {
489 | background: #0049cc;
490 | color: #fff;
491 | cursor: default;
492 | font-weight: bold;
493 | }
494 | }
495 | }
496 | }
497 |
498 | /* Quotes */
499 | blockquote, cite, q { // Sets consistent quote types
500 | font-style: italic
501 | quotes: none;
502 | }
503 |
504 | blockquote:before, blockquote:after,
505 | q:before, q:after {
506 | content: '';
507 | content: none
508 | }
509 |
510 | blockquote {
511 | border-left: 3px solid #dfdfdf;
512 | padding-left: @font-line-ratio * 1em;
513 | > p { padding: 0 }
514 | }
515 |
516 | /* Abbreviations */
517 | abbr, acronym, dfn {
518 | font-size: 80%;
519 | letter-spacing: .1em;
520 | line-height: 1.2;
521 | text-transform: uppercase;
522 | }
523 |
524 | abbr[title], acronym[title], dfn[title] { // Addresses styling not present in IE 8/9, Safari 5, and Chrome
525 | border-bottom: 1px dotted black;
526 | cursor: help;
527 | }
528 |
529 | /* Marks, inserts & deletes */
530 | ins, mark { text-decoration: none }
531 | ins { color: #f00; }
532 | del { text-decoration: line-through }
533 |
534 | mark { // Addresses styling not present in IE 8/9
535 | background: #c47529;
536 | color: #000
537 | }
538 |
539 | sub, sup { // Position 'sub' and 'sup' without affecting line-height
540 | font-size: 75%;
541 | line-height: 0;
542 | position: relative;
543 | vertical-align: baseline
544 | }
545 |
546 | sup { top: -0.7em } /* Move superscripted text up */
547 | sub { bottom: -0.25em } /* Move subscripted text down */
548 |
549 | /* Media */
550 | img, object, embed, video { // Fluid images
551 | max-width: 100%;
552 | }
553 |
554 | img { // Improve IE's resizing of images
555 | border: 0;
556 | -ms-interpolation-mode: bicubic;
557 | &::selection { background: transparent; }
558 | &::-moz-selection { background: transparent; }
559 |
560 | &.no-max { max-width: none; }
561 | }
562 |
563 | figure {
564 | margin: 0 0 1.6em;
565 | max-width: 100%;
566 |
567 | img {
568 | height: auto;
569 | width: 100%;
570 | }
571 |
572 | figcaption {
573 | background: #eee;
574 | border-left: 5px solid #999;
575 | margin-bottom: 0;
576 | padding: .4em .8em;
577 | }
578 | }
579 | svg:not(:root) { overflow: hidden } /* Correct IE9 overflow */
580 |
581 | ::-moz-selection,
582 | ::selection { // selected text
583 | background: #c47529;
584 | color: #fff;
585 | text-shadow: none
586 | }
587 |
588 |
589 | /*
590 | * Tables
591 | */
592 |
593 | table {
594 | border-collapse: collapse;
595 | border-spacing: 0;
596 | margin-bottom: @font-line-ratio * 1em;
597 | max-width: 100%;
598 | width: 100%;
599 |
600 | .striped > tbody > tr:nth-child(odd) > td { background: #f0f0f0; }
601 | }
602 |
603 | tr {
604 | display: table-row;
605 |
606 | .success td { background-color: #2ecc71; }
607 | .success-dark td { background-color: #27ad60; }
608 | .info td { background-color: #3498db; }
609 | .info-dark td { background-color: #2383c4; }
610 | .warning td { background-color: #f1c40f; }
611 | .warning-dark td { background-color: #cea70c; }
612 | .danger td { background-color: #e74c3c; }
613 | .danger-dark td { background-color: #dc2d1b; }
614 | }
615 |
616 | td,
617 | th {
618 | display: table-cell;
619 | padding: @font-size / 2 * 1px;
620 | }
621 |
622 | th {
623 | border-bottom: 2px solid #ddd;
624 | border-top: 0;
625 | vertical-align: bottom;
626 | }
627 |
628 | td {
629 | border-top: 1px solid #ddd;
630 | vertical-align: top;
631 | }
632 |
633 |
634 | /*
635 | Forms
636 | */
637 |
638 | form {
639 | border-bottom: 1px solid rgba(0, 0, 0, 0.1);
640 | margin-bottom: @font-size * 1.25 * 1px;
641 | padding: 0 0 @font-size * 1px;
642 |
643 | fieldset {
644 | border: 0;
645 | margin: 0;
646 | min-width: 0;
647 | padding: 0;
648 |
649 | legend {
650 | border: 0;
651 | border-bottom: 1px solid #e5e5e5;
652 | display: block;
653 | font-size: @font-size * 1.2 * 1px;
654 | padding: 0;
655 | width: 100%;
656 | }
657 | }
658 |
659 | label {
660 | display: inline-block;
661 | font-family: inherit;
662 | font-weight: bold;
663 | margin-bottom: @font-size / 2 * 1px;
664 | max-width: 100%;
665 |
666 | &.firm { color: #1abc9c; }
667 | &.success { color: #11b452; }
668 | &.info { color: #3498db; }
669 | &.warning { color: #f1c40f; }
670 | &.danger { color: #e74c3c; }
671 | &.night { color: #34495e; }
672 | }
673 |
674 | textarea,
675 | input[type=text],
676 | input[type=password],
677 | input[type=email],
678 | input[type=number] {
679 | .box-shadow(inset 0 -1px 0 #ddd);
680 | .transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
681 | background: rgba(0, 0, 0, 0);
682 | border: none;
683 | color: #666;
684 | font-size: @font-size*1px;
685 | display: block;
686 | min-height: @line-height * 1px;
687 | line-height: @line-height * 1px;
688 | padding: 0;
689 | width: 100%;
690 |
691 | &:focus {
692 | .box-shadow(inset 0 -2px 0 #2196F3);
693 | border-color: #66AFE9;
694 | outline: 0;
695 | }
696 |
697 | &.firm { border-color: #1abc9c; }
698 | &.success { border-color: #11b452; }
699 | &.info { border-color: #3498db; }
700 | &.warning { border-color: #f1c40f; }
701 | &.danger { border-color: #e74c3c; }
702 | }
703 |
704 | select[multiple],
705 | select[size],
706 | textarea { height: auto; }
707 |
708 | select {
709 | .transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
710 | background-color: #fff;
711 | border: 1px solid #ccc;
712 | font-size: @font-size * 1px;
713 | line-height: @line-height * 1px;
714 | margin: 0;
715 | padding: 0.3em 0.2em;
716 | position: relative;
717 | top: -4px;
718 | width: 100%;
719 |
720 | &:focus {
721 | border-color: #66AFE9;
722 | outline: 0;
723 | }
724 | }
725 |
726 | &.no-border { border-bottom: none; }
727 |
728 | .input-row {
729 | .internal-gutter-horizontal();
730 | margin-bottom: @font-size * 1px;
731 | position: relative;
732 | }
733 |
734 | .input-group {
735 | border-collapse: separate;
736 | display: table;
737 | position: relative;
738 |
739 | .addon,
740 | .input,
741 | .button { display: table-cell; }
742 |
743 | .addon,
744 | .button {
745 | padding: 0 @font-size * 1px;
746 | vertical-align: middle;
747 | white-space: nowrap;
748 | width: 1%;
749 | }
750 |
751 | .button {
752 | font-size: 0;
753 | position: relative;
754 | white-space: nowrap;
755 | }
756 |
757 | .input {
758 | float: left;
759 | margin-bottom: 0;
760 | position: relative;
761 | width: 100%;
762 | z-index: 2;
763 | }
764 | }
765 | }
766 |
767 | form input[type="submit"],
768 | form input[type="reset"],
769 | html input[type="button"],
770 | form button,
771 | a.button {
772 | .border-radius(@radius);
773 | .transition(all 0.2s);
774 | .user-select(none);
775 | background: #fff;
776 | border: none;
777 | color: #666;
778 | cursor: pointer;
779 | display: inline-block;
780 | font-size: @font-size * 0.8 * 1px;
781 | font-weight: normal;
782 | line-height: @line-height * 0.8 * 1px;
783 | letter-spacing: .1px;
784 | margin: 0;
785 | padding: 7px 16px;
786 | position: relative;
787 | text-align: center;
788 | text-rendering: optimizeLegibility;
789 | text-transform: uppercase;
790 | top: -7px;
791 | vertical-align: middle;
792 | white-space: nowrap;
793 | -webkit-font-smoothing: antialiased;
794 |
795 | &:hover { .box-shadow(0 3px 6px rgba(0, 0, 0, 0.2), 0 3px 6px rgba(0, 0, 0, 0.28)); }
796 |
797 | &.success {
798 | background: #11b452;
799 | &:active { background: #27ad60; }
800 | }
801 |
802 | &.info {
803 | background: #3498db;
804 | &:active { background: #2383c4; }
805 | }
806 |
807 | &.warning {
808 | background: #f1c40f;
809 | &:active { background: #cea70c; }
810 | }
811 |
812 | &.danger {
813 | background: #e74c3c;
814 | &:active { background: #dc2d1b; }
815 | }
816 |
817 | &.submit {
818 | background: #2196f3;
819 | color: #fff;
820 | &:active { background: #285e8e; }
821 | }
822 | }
823 |
824 | /*
825 | Addresses styling for 'hidden' attribute not present in IE 8/9
826 | Re-set default cursor for disabled elements
827 | */
828 | [hidden] { display: none; }
829 | [disabled] { cursor: default; }
830 |
831 | :focus { outline: 0; }
832 |
833 |
834 | /*
835 | Componentry
836 | */
837 |
838 | // Grid
839 |
840 | // Classes for arbitrary use
841 | .clearfix { .od-clearfix() }
842 | .row { .od-row() }
843 |
844 | .col {
845 | .od-col();
846 | .od-internal-gutter-horizontal();
847 | }
848 |
849 | .col-no-gutter {
850 | .od-col();
851 | }
852 |
853 | .col-left-gutter {
854 | .od-col();
855 | .od-internal-gutter-left();
856 | }
857 |
858 | .col-right-gutter {
859 | .od-col();
860 | .od-internal-gutter-right();
861 | }
862 |
863 | .col-inverse {
864 | .od-col-inverse();
865 | .od-internal-gutter-horizontal();
866 | }
867 |
868 | .col-no-gutter-inverse {
869 | .od-col-inverse();
870 | }
871 |
872 | .col-left-gutter-inverse {
873 | .od-col-inverse();
874 | .od-internal-gutter-left();
875 | }
876 |
877 | .col-right-gutter-inverse {
878 | .od-col-inverse();
879 | .od-internal-gutter-right();
880 | }
881 |
882 | .col-inverse-no-gutter.width-1,
883 | .col-inverse.width-1,
884 | .col-no-gutter.width-1,
885 | .col.width-1 { width: 8.33333%; }
886 |
887 | .col-inverse-no-gutter.width-2,
888 | .col-inverse.width-2,
889 | .col-no-gutter.width-2,
890 | .col.width-2 { width: 16.66667%; }
891 |
892 | .col-inverse-no-gutter.width-3,
893 | .col-inverse.width-3,
894 | .col-no-gutter.width-3,
895 | .col.width-3 { width: 25%; }
896 |
897 | .col-inverse-no-gutter.width-4,
898 | .col-inverse.width-4,
899 | .col-no-gutter.width-4,
900 | .col.width-4 { width: 33.33333%; }
901 |
902 | .col-inverse-no-gutter.width-5,
903 | .col-inverse.width-5,
904 | .col-no-gutter.width-5,
905 | .col.width-5 { width: 41.66667%; }
906 |
907 | .col-inverse-no-gutter.width-6,
908 | .col-inverse.width-6,
909 | .col-no-gutter.width-6,
910 | .col.width-6 { width: 50%; }
911 |
912 | .col-inverse-no-gutter.width-7,
913 | .col-inverse.width-7,
914 | .col-no-gutter.width-7,
915 | .col.width-7 { width: 58.33333%; }
916 |
917 | .col-inverse-no-gutter.width-8,
918 | .col-inverse.width-8,
919 | .col-no-gutter.width-8,
920 | .col.width-8 { width: 66.66667%; }
921 |
922 | .col-inverse-no-gutter.width-9,
923 | .col-inverse.width-9,
924 | .col-no-gutter.width-9,
925 | .col.width-9 { width: 75%; }
926 |
927 | .col-inverse-no-gutter.width-10,
928 | .col-inverse.width-10,
929 | .col-no-gutter.width-10,
930 | .col.width-10 { width: 83.33333%; }
931 |
932 | .col-inverse-no-gutter.width-11,
933 | .col-inverse.width-11,
934 | .col-no-gutter.width-11,
935 | .col.width-11 { width: 91.66667%; }
936 |
937 | .col-inverse-no-gutter.width-12,
938 | .col-inverse.width-12,
939 | .col-no-gutter.width-12,
940 | .col.width-12 { width: 100%; }
941 |
942 |
943 | /* Size specific stuff. Stops people screwing themselves up on mobile devices, mostly */
944 |
945 | @media screen and (max-width: 799px) {
946 | .col-inverse-no-gutter.width-13,
947 | .col-inverse.width-13,
948 | .col-no-gutter.width-13,
949 | .col.width-13,
950 | .col-inverse-no-gutter.width-14,
951 | .col-inverse.width-14,
952 | .col-no-gutter.width-14,
953 | .col.width-14,
954 | .col-inverse-no-gutter.width-15,
955 | .col-inverse.width-15,
956 | .col-no-gutter.width-15,
957 | .col.width-15,
958 | .col-inverse-no-gutter.width-16,
959 | .col-inverse.width-16,
960 | .col-no-gutter.width-16,
961 | .col.width-16,
962 | .col-inverse-no-gutter.width-17,
963 | .col-inverse.width-17,
964 | .col-no-gutter.width-17,
965 | .col.width-17,
966 | .col-inverse-no-gutter.width-18,
967 | .col-inverse.width-18,
968 | .col-no-gutter.width-18,
969 | .col.width-18,
970 | .col-inverse-no-gutter.width-19,
971 | .col-inverse.width-19,
972 | .col-no-gutter.width-19,
973 | .col.width-19,
974 | .col-inverse-no-gutter.width-20,
975 | .col-inverse.width-20,
976 | .col-no-gutter.width-20,
977 | .col.width-20,
978 | .col-inverse-no-gutter.width-21,
979 | .col-inverse.width-21,
980 | .col-no-gutter.width-21,
981 | .col.width-21,
982 | .col-inverse-no-gutter.width-22,
983 | .col-inverse.width-22,
984 | .col-no-gutter.width-22,
985 | .col.width-22,
986 | .col-inverse-no-gutter.width-23,
987 | .col-inverse.width-23,
988 | .col-no-gutter.width-23,
989 | .col.width-23,
990 | .col-inverse-no-gutter.width-24,
991 | .col-inverse.width-24,
992 | .col-no-gutter.width-24,
993 | .col.width-24 { width: 100%; }
994 | }
995 |
996 | @media screen and (min-width: 800px) {
997 | .col-inverse-no-gutter.width-13,
998 | .col-inverse.width-13,
999 | .col-no-gutter.width-13,
1000 | .col.width-13 { width: 108.33333%; }
1001 |
1002 | .col-inverse-no-gutter.width-14,
1003 | .col-inverse.width-14,
1004 | .col-no-gutter.width-14,
1005 | .col.width-14 { width: 116.66667%; }
1006 |
1007 | .col-inverse-no-gutter.width-15,
1008 | .col-inverse.width-15,
1009 | .col-no-gutter.width-15,
1010 | .col.width-15 { width: 125%; }
1011 |
1012 | .col-inverse-no-gutter.width-16,
1013 | .col-inverse.width-16,
1014 | .col-no-gutter.width-16,
1015 | .col.width-16 { width: 133.33333%; }
1016 |
1017 | .col-inverse-no-gutter.width-17,
1018 | .col-inverse.width-17,
1019 | .col-no-gutter.width-17,
1020 | .col.width-17 { width: 141.66667%; }
1021 |
1022 | .col-inverse-no-gutter.width-18,
1023 | .col-inverse.width-18,
1024 | .col-no-gutter.width-18,
1025 | .col.width-18 { width: 150%; }
1026 |
1027 | .col-inverse-no-gutter.width-19,
1028 | .col-inverse.width-19,
1029 | .col-no-gutter.width-19,
1030 | .col.width-19 { width: 158.33333%; }
1031 |
1032 | .col-inverse-no-gutter.width-20,
1033 | .col-inverse.width-20,
1034 | .col-no-gutter.width-20,
1035 | .col.width-20 { width: 166.66667%; }
1036 |
1037 | .col-inverse-no-gutter.width-21,
1038 | .col-inverse.width-21,
1039 | .col-no-gutter.width-21,
1040 | .col.width-21 { width: 175%; }
1041 |
1042 | .col-inverse-no-gutter.width-22,
1043 | .col-inverse.width-22,
1044 | .col-no-gutter.width-22,
1045 | .col.width-22 { width: 183.33333%; }
1046 |
1047 | .col-inverse-no-gutter.width-23,
1048 | .col-inverse.width-23,
1049 | .col-no-gutter.width-23,
1050 | .col.width-23 { width: 191.66667%; }
1051 |
1052 | .col-inverse-no-gutter.width-24,
1053 | .col-inverse.width-24,
1054 | .col-no-gutter.width-24,
1055 | .col.width-24 { width: 200%; }
1056 |
1057 |
1058 | .col-inverse-no-gutter.width-offset-0,
1059 | .col-inverse.width-offset-0,
1060 | .col-no-gutter.width-offset-0,
1061 | .col.width-offset-0 { margin-left: 0%; }
1062 |
1063 | .col-inverse-no-gutter.width-offset-1,
1064 | .col-inverse.width-offset-1,
1065 | .col-no-gutter.width-offset-1,
1066 | .col.width-offset-1 { margin-left: 8.33333%; }
1067 |
1068 | .col-inverse-no-gutter.width-offset-2,
1069 | .col-inverse.width-offset-2,
1070 | .col-no-gutter.width-offset-2,
1071 | .col.width-offset-2 { margin-left: 16.66667%; }
1072 |
1073 | .col-inverse-no-gutter.width-offset-3,
1074 | .col-inverse.width-offset-3,
1075 | .col-no-gutter.width-offset-3,
1076 | .col.width-offset-3 { margin-left: 25%; }
1077 |
1078 | .col-inverse-no-gutter.width-offset-4,
1079 | .col-inverse.width-offset-4,
1080 | .col-no-gutter.width-offset-4,
1081 | .col.width-offset-4 { margin-left: 33.33333%; }
1082 |
1083 | .col-inverse-no-gutter.width-offset-5,
1084 | .col-inverse.width-offset-5,
1085 | .col-no-gutter.width-offset-5,
1086 | .col.width-offset-5 { margin-left: 41.66667%; }
1087 |
1088 | .col-inverse-no-gutter.width-offset-6,
1089 | .col-inverse.width-offset-6,
1090 | .col-no-gutter.width-offset-6,
1091 | .col.width-offset-6 { margin-left: 50%; }
1092 |
1093 | .col-inverse-no-gutter.width-offset-7,
1094 | .col-inverse.width-offset-7,
1095 | .col-no-gutter.width-offset-7,
1096 | .col.width-offset-7 { margin-left: 58.33333%; }
1097 |
1098 | .col-inverse-no-gutter.width-offset-8,
1099 | .col-inverse.width-offset-8,
1100 | .col-no-gutter.width-offset-8,
1101 | .col.width-offset-8 { margin-left: 66.66667%; }
1102 |
1103 | .col-inverse-no-gutter.width-offset-9,
1104 | .col-inverse.width-offset-9,
1105 | .col-no-gutter.width-offset-9,
1106 | .col.width-offset-9 { margin-left: 75%; }
1107 |
1108 | .col-inverse-no-gutter.width-offset-10,
1109 | .col-inverse.width-offset-10,
1110 | .col-no-gutter.width-offset-10,
1111 | .col.width-offset-10 { margin-left: 83.33333%; }
1112 |
1113 |
1114 | .col-inverse-no-gutter.push,
1115 | .col-inverse.push,
1116 | .col-no-gutter.push,
1117 | .col.push { right: auto; }
1118 |
1119 | .col-inverse-no-gutter.pull,
1120 | .col-inverse.pull,
1121 | .col-no-gutter.pull,
1122 | .col.pull { left: auto; }
1123 |
1124 |
1125 | .col-inverse-no-gutter.push-1,
1126 | .col-inverse.push-1,
1127 | .col-no-gutter.push-1,
1128 | .col.push-1 {
1129 | margin-left: -8.33333%;
1130 | left: 8.33333%;
1131 | }
1132 |
1133 | .col-inverse-no-gutter.push-2,
1134 | .col-inverse.push-2,
1135 | .col-no-gutter.push-2,
1136 | .col.push-2 {
1137 | margin-left: -16.66667%;
1138 | left: 16.66667%;
1139 | }
1140 |
1141 | .col-inverse-no-gutter.push-3,
1142 | .col-inverse.push-3,
1143 | .col-no-gutter.push-3,
1144 | .col.push-3 {
1145 | margin-left: -25%;
1146 | left: 25%;
1147 | }
1148 |
1149 | .col-inverse-no-gutter.push-4,
1150 | .col-inverse.push-4,
1151 | .col-no-gutter.push-4,
1152 | .col.push-4 {
1153 | margin-left: -33.33333%;
1154 | left: 33.33333%;
1155 | }
1156 |
1157 | .col-inverse-no-gutter.push-5,
1158 | .col-inverse.push-5,
1159 | .col-no-gutter.push-5,
1160 | .col.push-5 {
1161 | margin-left: -41.66667%;
1162 | left: 41.66667%;
1163 | }
1164 |
1165 | .col-inverse-no-gutter.push-6,
1166 | .col-inverse.push-6,
1167 | .col-no-gutter.push-6,
1168 | .col.push-6 {
1169 | margin-left: -50%;
1170 | left: 50%;
1171 | }
1172 |
1173 | .col-inverse-no-gutter.push-7,
1174 | .col-inverse.push-7,
1175 | .col-no-gutter.push-7,
1176 | .col.push-7 {
1177 | margin-left: -58.33333%;
1178 | left: 58.33333%;
1179 | }
1180 |
1181 | .col-inverse-no-gutter.push-8,
1182 | .col-inverse.push-8,
1183 | .col-no-gutter.push-8,
1184 | .col.push-8 {
1185 | margin-left: -66.66667%;
1186 | left: 66.66667%;
1187 | }
1188 |
1189 | .col-inverse-no-gutter.push-9,
1190 | .col-inverse.push-9,
1191 | .col-no-gutter.push-9,
1192 | .col.push-9 {
1193 | margin-left: -75%;
1194 | left: 75%;
1195 | }
1196 |
1197 | .col-inverse-no-gutter.push-10,
1198 | .col-inverse.push-10,
1199 | .col-no-gutter.push-10,
1200 | .col.push-10 {
1201 | margin-left: -83.33333%;
1202 | left: 83.33333%;
1203 | }
1204 |
1205 | .col-inverse-no-gutter.push-11,
1206 | .col-inverse.push-11,
1207 | .col-no-gutter.push-11,
1208 | .col.push-11 {
1209 | margin-left: -91.66667%;
1210 | left: 91.66667%;
1211 | }
1212 |
1213 |
1214 | .col-inverse-no-gutter.pull-1,
1215 | .col-inverse.pull-1,
1216 | .col-no-gutter.pull-1,
1217 | .col.pull-1 {
1218 | margin-right: -8.33333%;
1219 | right: 8.33333%;
1220 | }
1221 |
1222 | .col-inverse-no-gutter.pull-2,
1223 | .col-inverse.pull-2,
1224 | .col-no-gutter.pull-2,
1225 | .col.pull-2 {
1226 | margin-right: -16.66667%;
1227 | right: 16.66667%;
1228 | }
1229 |
1230 | .col-inverse-no-gutter.pull-3,
1231 | .col-inverse.pull-3,
1232 | .col-no-gutter.pull-3,
1233 | .col.pull-3 {
1234 | margin-right: -25%;
1235 | right: 25%;
1236 | }
1237 |
1238 | .col-inverse-no-gutter.pull-4,
1239 | .col-inverse.pull-4,
1240 | .col-no-gutter.pull-4,
1241 | .col.pull-4 {
1242 | margin-right: -33.33333%;
1243 | right: 33.33333%;
1244 | }
1245 |
1246 | .col-inverse-no-gutter.pull-5,
1247 | .col-inverse.pull-5,
1248 | .col-no-gutter.pull-5,
1249 | .col.pull-5 {
1250 | margin-right: -41.66667%;
1251 | right: 41.66667%;
1252 | }
1253 |
1254 | .col-inverse-no-gutter.pull-6,
1255 | .col-inverse.pull-6,
1256 | .col-no-gutter.pull-6,
1257 | .col.pull-6 {
1258 | margin-right: -50%;
1259 | right: 50%;
1260 | }
1261 |
1262 | .col-inverse-no-gutter.pull-7,
1263 | .col-inverse.pull-7,
1264 | .col-no-gutter.pull-7,
1265 | .col.pull-7 {
1266 | margin-right: -58.33333%;
1267 | right: 58.33333%;
1268 | }
1269 |
1270 | .col-inverse-no-gutter.pull-8,
1271 | .col-inverse.pull-8,
1272 | .col-no-gutter.pull-8,
1273 | .col.pull-8 {
1274 | margin-right: -66.66667%;
1275 | right: 66.66667%;
1276 | }
1277 |
1278 | .col-inverse-no-gutter.pull-9,
1279 | .col-inverse.pull-9,
1280 | .col-no-gutter.pull-9,
1281 | .col.pull-9 {
1282 | margin-right: -75%;
1283 | right: 75%;
1284 | }
1285 |
1286 | .col-inverse-no-gutter.pull-10,
1287 | .col-inverse.pull-10,
1288 | .col-no-gutter.pull-10,
1289 | .col.pull-10 {
1290 | margin-right: -83.33333%;
1291 | right: 83.33333%;
1292 | }
1293 |
1294 | .col-inverse-no-gutter.pull-11,
1295 | .col-inverse.pull-11,
1296 | .col-no-gutter.pull-11,
1297 | .col.pull-11 {
1298 | margin-right: -91.66667%;
1299 | right: 91.66667%;
1300 | }
1301 |
1302 |
1303 | .col-inverse-no-gutter.centered,
1304 | .col-inverse.centered,
1305 | .col-no-gutter.centered,
1306 | .col.centered {
1307 | float: none;
1308 | margin: 0 auto;
1309 | }
1310 | }
1311 |
1312 | .gutter { .od-gutter(); }
1313 | .gutter-horizontal { .od-gutter-horizontal(); }
1314 | .gutter-vertical { .od-gutter-vertical(); }
1315 |
1316 | .gutter-top { .od-gutter-top(); }
1317 | .gutter-right { .od-gutter-right(); }
1318 | .gutter-bottom { .od-gutter-bottom(); }
1319 | .gutter-left { .od-gutter-left(); }
1320 |
1321 | .internal-gutter { .od-internal-gutter(); }
1322 | .internal-gutter-horizontal { .od-internal-gutter-horizontal(); }
1323 | .internal-gutter-vertical { .od-internal-gutter-vertical(); }
1324 |
1325 | .internal-gutter-top { .od-internal-gutter-top(); }
1326 | .internal-gutter-right { .od-internal-gutter-right(); }
1327 | .internal-gutter-bottom { .od-internal-gutter-bottom(); }
1328 | .internal-gutter-left { .od-internal-gutter-left(); }
1329 |
1330 |
1331 | // media styling
1332 |
1333 | figure.col { padding-left: 0; }
1334 | figure.col-inverse { padding-right: 0; }
1335 |
1336 |
1337 | /*
1338 | Font Stacks
1339 |
1340 | Sans font stacks from http://www.awayback.com/revised-font-stack/
1341 | Other types of font stacks from http://cssfontstack.com/
1342 | */
1343 |
1344 | .monospace() { font-family: "Andale Mono", "Courier New", Courier, monospace; }
1345 | .serif() { font-family: "Hoefler Text", Garamond, Baskerville, "Baskerville Old Face", "Times New Roman", serif; }
1346 | .sans() { font-family: "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Verdana, Tahoma, sans-serif; }
1347 | .elegant() { font-family: Baskerville, Garamond, Palatino, "Palatino Linotype", "Hoefler Text", "Times New Roman", serif; }
1348 | .readable() { font-family: "Lucida Grande", geneva, helvetica, sans-serif; }
1349 |
1350 | // Serif
1351 | .baskerville() { font-family: Baskerville, "Baskerville old face", "Hoefler Text", Garamond, "Times New Roman", serif; }
1352 | .caslon() { font-family: "Big Caslon", "Book Antiqua", "Palatino Linotype", Georgia, serif; }
1353 | .bodoni() { font-family: "Bodoni MT", Didot, "Didot LT STD", "Hoefler Text", Garamond, "Times New Roman", serif; }
1354 | .book-antiqua() { font-family: "Book Antiqua", Palatino, "Palatino Linotype", "Palatino LT STD", Georgia, serif; }
1355 | .cambria() { font-family: Cambria, Georgia, serif; }
1356 | .constantia() { font-family: Constantia, Palatino, "Palatino Linotype", "Palatino LT STD", Georgia, serif; }
1357 | .didot() { font-family: Didot, "Didot LT STD", "Hoefler Text", Garamond, "Times New Roman", serif; }
1358 | .garamond() { font-family: Garamond, Baskerville, "Baskerville Old Face", "Hoefler Text", "Times New Roman", serif; }
1359 | .goudy() { font-family: "Goudy Old Style", Garamond, "Big Caslon", "Times New Roman", serif; }
1360 | .hoefler() { font-family: "Hoefler Text", "Baskerville old face", Garamond, "Times New Roman", serif; }
1361 | .lucidia-serif() { font-family: "Lucida Bright", Georgia, serif; }
1362 | .palantino() { font-family: Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif; }
1363 |
1364 | // Sans
1365 | .calibri() { font-family: Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif; }
1366 | .franklin() { font-family: "Franklin Gothic Medium", Arial, sans-serif; }
1367 | .futura() { font-family: Futura, "Trebuchet MS", Arial, sans-serif; }
1368 | .geneva() { font-family: Geneva, Tahoma, Verdana, sans-serif; }
1369 | .gill() { font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif; }
1370 | .helvetica() { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
1371 | .lucidia-sans() { font-family: "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; }
1372 | .optima() { font-family: Optima, Segoe, "Segoe UI", Candara, Calibri, Arial, sans-serif; }
1373 | .segoe() { font-family: Segoe, "Segoe UI", "Helvetica Neue", Arial, sans-serif; }
1374 | .tahoma() { font-family: Tahoma, Geneva, Verdana, sans-serif; }
1375 | .trebuchet() { font-family: "Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif; }
1376 | .verdana() { font-family: Verdana, Geneva, sans-serif; }
1377 |
1378 | // Other
1379 | .avant() { font-family: "Avant Garde", Avantgarde, "Century Gothic", CenturyGothic, "AppleGothic", sans-serif; }
1380 | .brush() { font-family: "Brush Script MT", cursive; }
1381 | .copperplate() { font-family: Copperplate, "Copperplate Gothic Light", fantasy; }
1382 | .impact() { font-family: Impact, Haettenschweiler, "Franklin Gothic Bold", Charcoal, "Helvetica Inserat", "Bitstream Vera Sans Bold", "Arial Black", sans serif; }
1383 | .papyrus() { font-family: Papyrus, fantasy; }
1384 | .rockwell() { font-family: Rockwell, "Courier Bold", Courier, Georgia, Times, "Times New Roman", serif; }
1385 |
1386 |
1387 | /*
1388 | Boxes
1389 | */
1390 |
1391 | .od-modal-settings (@background, @border-width: 1px, @border-ype: solid, @border-colour, @color) {
1392 | background: @background;
1393 | border: @border-width @border-ype @border-colour;
1394 | color: @color;
1395 | }
1396 |
1397 | .modal,
1398 | .download-modal,
1399 | .info-modal,
1400 | .note-modal,
1401 | .warning-modal {
1402 | .border-radius(@radius);
1403 | .box-shadow(0 5px 15px rgba(0, 0, 0, 0.5));
1404 | background-clip: padding-box;
1405 | background-color: #fff;
1406 | border: 1px solid rgba(0, 0, 0, 0);
1407 | outline: 0;
1408 | position: relative;
1409 |
1410 | .modal-header,
1411 | .modal-body,
1412 | .modal-footer { padding: @font-size * 1px; }
1413 |
1414 | .modal-header {
1415 | border-bottom: 1px solid rgba(0, 0, 0, 0);
1416 | min-height: @font-size * 1px;
1417 | }
1418 |
1419 | .modal-body { position: relative; }
1420 |
1421 | .modal-footer {
1422 | border-top: 1px solid rgba(0, 0, 0, 0);
1423 | text-align: right;
1424 | font-style: italic;
1425 | }
1426 | }
1427 |
1428 | .box {
1429 | .border-radius(@radius);
1430 | background-clip: padding-box;
1431 | background-color: #fff;
1432 | border: 1px solid rgba(0, 0, 0, 0);
1433 | outline: 0;
1434 | padding: 5px;
1435 | position: relative;
1436 | }
1437 |
1438 | /*
1439 | Colours
1440 | */
1441 |
1442 | .palette-success { background-color: #2ecc71; }
1443 | .palette-warning { background-color: #f1c40f; }
1444 | .palette-danger { background-color: #e74c3c; }
1445 | .palette-submit { background-color: #2196f3; }
1446 |
1447 | .palette-success-dark {
1448 | background-color: #27ad60;
1449 | color: #fff;
1450 | }
1451 | .palette-info {
1452 | background-color: #dbc034;
1453 | color: #fff;
1454 | }
1455 | .palette-info-dark {
1456 | background-color: #a88f0b;
1457 | color: #fff;
1458 | }
1459 | .palette-warning-dark {
1460 | background-color: #cea70c;
1461 | color: #fff;
1462 | }
1463 | .palette-danger-dark {
1464 | background-color: #dc2d1b;
1465 | color: #fff;
1466 | }
1467 | .palette-submit-dark {
1468 | background-color: #285e8e;
1469 | color: #fff;
1470 | }
1471 |
1472 | // import resets and base units
1473 | @import "style.less";
1474 |
--------------------------------------------------------------------------------
/app/less/size_0.less:
--------------------------------------------------------------------------------
1 | body {
2 | background: #f9f9f9;
3 | overflow-x: hidden;
4 | }
5 |
6 | #bg {
7 | background: #333;
8 | position: absolute;
9 | top: 0; left: 0;
10 | z-index: -1;
11 |
12 | &:after {
13 | border-left: 2000px solid rgba(0, 0, 0, 0);
14 | border-right: 0 solid rgba(0, 0, 0, 0);
15 | border-bottom: 200px solid #F9F9F9;
16 | clear: both;
17 | content: '';
18 | height: 0;
19 | left: 0;
20 | position: absolute;
21 | bottom: 0;
22 | width: 0;
23 | }
24 | }
25 |
26 | #hohContainer { .od-row(); }
27 |
28 | #heading {
29 | .od-row();
30 |
31 | #main_header { margin: 0 auto; }
32 |
33 | #logo_container,
34 | #powered_by {
35 | .od-col();
36 | .od-width-6();
37 | }
38 |
39 | #logo_container p {
40 | text-align: left;
41 |
42 | a { border-bottom: none; }
43 | }
44 |
45 | #powered_by ul {
46 | text-align: right;
47 |
48 | #reactjs a {
49 | color: #00d8ff;
50 | font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
51 |
52 | img {
53 | height: 25px;
54 | position: relative;
55 | top: 7px;
56 | width: 25px;
57 | }
58 | }
59 |
60 | #wikipedia a {
61 | color: #fff;
62 | font-family: 'Crimson+Text';
63 | letter-spacing: 0.1em;
64 | text-transform: uppercase;
65 |
66 | small {
67 | font-size: 0.8em
68 | }
69 | }
70 | }
71 |
72 | h1 {
73 | color: #fff;
74 | clear: both;
75 | margin-top: 100px;
76 | margin-bottom: 0;
77 | text-align: center;
78 |
79 | #top_title {
80 | font-size: 32px;
81 | font-family: 'Open Sans';
82 | font-weight: 300;
83 | letter-spacing: .25em;
84 | text-transform: uppercase;
85 | }
86 |
87 | #lower_title {
88 | font-size: 28px;
89 | font-family: 'Amiri';
90 | font-style: italic;
91 | position: relative;
92 | top: -1em;
93 | }
94 | }
95 |
96 | p {
97 | color: #fff;
98 | font-family: 'Amiri';
99 | font-style: italic;
100 | margin-bottom: 1em;
101 | text-align: center;
102 |
103 | &:last-child { margin-bottom: 0 }
104 |
105 | a {
106 | border-bottom: 1px dotted #fff;
107 | color: #fff;
108 | }
109 | }
110 | }
111 |
112 | #socialButtons {
113 | .transition(all 0.5s);
114 | color: #00b5ff;
115 | position: absolute;
116 | right: 0.5em;
117 |
118 | &:hover,
119 | &.active { color: #535f5f; }
120 |
121 | .socialBox {
122 | height: 36px;
123 | position: relative;
124 | width: 41px;
125 | }
126 |
127 | #socialIcons {
128 | .od-row();
129 | bottom: 37px;
130 | position: absolute;
131 | right: 5px;
132 | }
133 |
134 | #circleBg {
135 | .border-radius(5px);
136 | background-color: #fff;
137 | display: block;
138 | position: relative;
139 | right: 0.9em;
140 |
141 | .fa-share-alt-square {
142 | left: -1px;
143 | top: -4px;
144 | }
145 | }
146 |
147 | .fa {
148 | cursor: pointer;
149 | position: relative;
150 | }
151 |
152 | .fa-share-alt-square { font-size: 2em; }
153 |
154 | .count,
155 | .share {
156 | text-align: center;
157 | text-decoration: none;
158 | }
159 |
160 | .count {
161 | color: #fff;
162 | font-size: 14px;
163 | left: -50px;
164 | position: absolute;
165 | text-align: right;
166 | top: 6px;
167 | width: 42px;
168 | }
169 |
170 | .share {
171 | .border-radius(50%);
172 | color: #fff;
173 | display: inline-block;
174 | height: 30px;
175 | line-height: 28px;
176 | position: absolute;
177 | width: 31px;
178 |
179 | &:hover {
180 | color: #fff;
181 | text-decoration: none;
182 | }
183 | }
184 |
185 | .fa img {
186 | position: relative;
187 | top: 2px;
188 | width: 16px;
189 | }
190 |
191 | .facebook,
192 | .twitter,
193 | .pinterest,
194 | .stumbleupon,
195 | .bufferapp {
196 | height:100%;
197 | text-align:center;
198 | width:100%;
199 | .border-radius(4px);
200 | }
201 |
202 | #twitter .share {
203 | text-shadow: 1px 0 0 #0077be;
204 | .background-image(linear-gradient(top, #26c3eb 0%, #0080d6 100%));
205 | }
206 |
207 | #facebook .share {
208 | background:#3b5998;
209 | text-shadow:1px 0 0 #26427e;
210 | .background-image(linear-gradient(top, #3B5998 0%, #133783 100%));
211 | }
212 |
213 | #googleplus .share {
214 | background:#6d6d6d;
215 | text-shadow:1px 0 0 #222;
216 | .background-image(linear-gradient(top, #6d6d6d 0%, #434343 100%));
217 | }
218 |
219 | #linkedin .share {
220 | background:#6d6d6d;
221 | text-shadow:1px 0 0 #26427e;
222 | .background-image(linear-gradient(top, #74bbdb 0%, #007fb2 100%));
223 | }
224 |
225 | #stumbleupon .share {
226 | background: #eb4924;
227 | text-shadow: 1px 0 0 #26427e;
228 | .background-image(linear-gradient(top, #eb4924 0%, #b12403 100%));
229 | }
230 | }
231 |
232 | .socialTransition-appear {
233 | .transition(all 2s);
234 | max-height: 1px;
235 | opacity: 0.01;
236 |
237 | &.socialTransition-appear-active {
238 | max-height: 500px;
239 | opacity: 1;
240 | }
241 | }
242 |
243 | #mapAndControls,
244 | #controls,
245 | #items,
246 | #itemDetail {
247 | .od-row();
248 | width: 1200px;
249 | }
250 |
251 | #mapAndControls { position: relative; }
252 |
253 | #gmap { .box-shadow(0 10px 55px 0 rgba(0, 0, 0, 0.3)); }
254 |
255 | #mapCanvas { display: block; }
256 |
257 | #controls {
258 | background: rgba(0, 0, 0, 0.5);
259 | bottom: 0;
260 | padding: 11px 11px 18px;
261 | position: absolute;
262 |
263 | p {
264 | .border-radius(3px);
265 | background: #fff;
266 | cursor: pointer;
267 | margin-bottom: 0;
268 | padding: 0.2em 0.5em;
269 | text-transform: capitalize;
270 | }
271 |
272 | label {
273 | color: #fff;
274 | margin-bottom: 0.2em;
275 | }
276 |
277 | .panel {
278 | .od-col();
279 | .od-width-4();
280 | .od-internal-gutter-horizontal();
281 | }
282 |
283 | .yearPanel {
284 | .border-radius(3px);
285 | background-color: #FFF;
286 | display: inline-block;
287 | font-size: 15px;
288 | padding: 3px 9px;
289 | }
290 |
291 | #startDate,
292 | #endDate {
293 | cursor: pointer;
294 | display: inline-block;
295 | margin: 0 1em 0 22px;
296 | width: 280px;
297 | }
298 | }
299 |
300 | .fa_button {
301 | .box-sizing(content-box);
302 | .border-radius(50%);
303 | .box-shadow(1px 1px 1px #CCC);
304 | .transition(background-color 0.5s);
305 | background-color: #00b5ff;
306 | border: none;
307 | color: #fff;
308 | cursor: pointer;
309 | display: block;
310 | height: 30px;
311 | outline: none;
312 | text-align: center;
313 | text-decoration: none;
314 | width: 30px;
315 | zoom: 1;
316 |
317 | backButton,
318 | forwardButton,
319 | galleryBack,
320 | galleryForward {
321 | cursor: pointer;
322 | font-size: 18px;
323 | position: absolute;
324 |
325 | .fa {
326 | position: relative;
327 | top: 1px;
328 | }
329 | }
330 |
331 | backButton,
332 | forwardButton {
333 | bottom: 35px;
334 | }
335 |
336 | backButton { left: -50px; }
337 | forwardButton { right: -50px; }
338 |
339 | backButton .fa,
340 | galleryBack .fa {
341 | left: -1px;
342 | }
343 |
344 | forwardButton .fa,
345 | galleryForward .fa {
346 | left: 1px;
347 | }
348 |
349 | &:hover {
350 | background-color: #535f5f;
351 | color: #fff;
352 | }
353 | }
354 |
355 | #items ul {
356 | list-style-type: none;
357 | margin-left: 0;
358 |
359 | .yearTitle {
360 | border-bottom: 1px solid #e8e8e8;
361 | color: #727272;
362 | margin: 60px 0 30px;
363 | padding-bottom: 30px;
364 | }
365 |
366 | .itemPanel {
367 | .box-shadow(0 2px 4px rgba(0, 0, 0, 0.24));
368 | background: #fff;
369 | cursor: pointer;
370 | margin-bottom: 30px;
371 |
372 | &.highlightMap { background-color: #d5edf5; }
373 | &.highlightClick { background-color: #f5f4d5; }
374 |
375 | p {
376 | margin-bottom: 0;
377 | padding: 1em;
378 |
379 | a { color: #727272; }
380 | }
381 |
382 | .readmore {
383 | border-top: 1px solid #eee;
384 | color: #00b5ff;
385 | display: block;
386 | font-size: 0.8em;
387 | padding: 1em;
388 | text-align: right;
389 | width: 100%;
390 | }
391 | }
392 | }
393 |
394 | .itemDetailTransition-appear {
395 | opacity: 0.01;
396 | .transition(opacity .5s ease-in);
397 |
398 | &.itemDetailTransition-appear-active { opacity: 1; }
399 | }
400 |
401 | #itemDetail {
402 | .box-shadow(0 4px 10px rgba(0, 0, 0, 0.23));
403 | background: #fff;
404 | overflow-y: auto;
405 | padding: 1em;
406 | position: fixed;
407 | right: 15px;
408 | top: 10px;
409 |
410 | h3,
411 | h4 {
412 | border-bottom: 1px solid #e8e8e8;
413 | font-family: 'Crimson+Text';
414 | line-height: 1.5;
415 | padding-bottom: 1em;
416 | }
417 |
418 | h3 {
419 | font-size: 24px;
420 | margin: 0.5em 0 1.5em;
421 | }
422 |
423 | h4 {
424 | font-size: 20px;
425 | margin: 2em 0 1em;
426 | }
427 |
428 | p {
429 | font-size: 15px;
430 |
431 | mainLink {
432 | font-weight: bold;
433 |
434 | a { font-weight: normal; }
435 | }
436 | }
437 |
438 | ul {
439 | list-style-type: none;
440 | margin-left: 0;
441 |
442 | li {
443 | font-size: 15px;
444 | }
445 | }
446 |
447 | #galleryTitle {
448 | position: relative;
449 |
450 | #galleryBack,
451 | #galleryForward { top: 3px; }
452 |
453 | #galleryBack { left: 89px }
454 | #galleryForward { left: 130px }
455 | }
456 |
457 | #gallery img {
458 | .od-col();
459 | .od-width-4();
460 | .od-internal-gutter-horizontal();
461 | }
462 | }
463 |
464 | #hideItemDetail {
465 | .border-radius(50%);
466 | .box-shadow(1px 1px 1px #CCC);
467 | .transition(right 0.8s);
468 | background: #00b5ff;
469 | color: #fff;
470 | cursor: pointer;
471 | height: 35px;
472 | line-height: 2;
473 | position: fixed;
474 | right: -100%;
475 | text-align: center;
476 | top: 4px;
477 | width: 35px;
478 | z-index: 200;
479 | }
480 |
481 | //
482 | // pagination
483 | //
484 |
485 | .paginator {
486 | .od-inline();
487 | text-align: center;
488 |
489 | li {
490 | cursor: pointer;
491 | margin: 0;
492 | padding: 2px 10px;
493 |
494 | a { color: #ccc; }
495 |
496 | &.selected {
497 | padding: 2px 10px;
498 |
499 | a { color: #00b5ff; }
500 | }
501 |
502 | &.no_more {
503 | .border-radius(2px);
504 | background-color: #535f5f;
505 | padding: 2px 10px;
506 |
507 | a { color: #fff; }
508 | }
509 |
510 | &:hover {
511 | padding: 2px 10px;
512 |
513 | a { color: #535f5f; }
514 | }
515 | }
516 | }
517 |
518 | #footer {
519 | background: #222;
520 | color: #ccc;
521 |
522 | p {
523 | border-top: 1px solid #fff;
524 | color: #fff;
525 | margin-bottom: 0;
526 | padding: 2em;
527 | text-align: center;
528 | }
529 |
530 | a {
531 | border-bottom: 1px dotted #ccc;
532 | color: #ccc;
533 | }
534 | }
--------------------------------------------------------------------------------
/app/less/size_1024.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwatsonwailes/history-of-humanity/d8867d65a248c4711059dba62b56fab14cf79a13/app/less/size_1024.less
--------------------------------------------------------------------------------
/app/less/size_1024_1376.less:
--------------------------------------------------------------------------------
1 | #hohContainer,
2 | #heading { width: 980px; }
3 |
4 | #heading { margin: 75px auto; }
5 |
6 | #circleBg {
7 | height: 30px;
8 | width: 30px;
9 |
10 | .fa-share-alt-square { font-size: 2.3em; }
11 | }
12 |
13 | #mapAndControls,
14 | #controls,
15 | #items,
16 | #itemDetail { width: 900px; }
17 |
18 | #mapCanvas {
19 | height: 600px;
20 | width: 900px;
21 | }
22 |
23 | #controls {
24 | #startDate,
25 | #endDate { width: 200px; }
26 | }
27 |
28 | #hideItemDetail { right: 897px; }
--------------------------------------------------------------------------------
/app/less/size_1024_up.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwatsonwailes/history-of-humanity/d8867d65a248c4711059dba62b56fab14cf79a13/app/less/size_1024_up.less
--------------------------------------------------------------------------------
/app/less/size_1376.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwatsonwailes/history-of-humanity/d8867d65a248c4711059dba62b56fab14cf79a13/app/less/size_1376.less
--------------------------------------------------------------------------------
/app/less/size_1376_1840.less:
--------------------------------------------------------------------------------
1 | #hohContainer,
2 | #heading { width: 1280px; }
3 |
4 | #heading { margin: 100px auto; }
5 |
6 | #circleBg {
7 | height: 30px;
8 | width: 30px;
9 | }
10 |
11 | #mapAndControls,
12 | #controls,
13 | #items,
14 | #itemDetail { width: 1200px; }
15 |
16 | #mapCanvas {
17 | height: 600px;
18 | width: 1200px;
19 | }
20 |
21 | #controls {
22 | #startDate,
23 | #endDate { width: 280px; }
24 | }
25 |
26 | #hideItemDetail {
27 | height: 28px;
28 | line-height: 1.6;
29 | right: 1197px;
30 | width: 28px;
31 | }
32 |
--------------------------------------------------------------------------------
/app/less/size_1376_up.less:
--------------------------------------------------------------------------------
1 | body { font-size: (@font-size + 2)/@em; }
--------------------------------------------------------------------------------
/app/less/size_1840.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwatsonwailes/history-of-humanity/d8867d65a248c4711059dba62b56fab14cf79a13/app/less/size_1840.less
--------------------------------------------------------------------------------
/app/less/size_1840_up.less:
--------------------------------------------------------------------------------
1 | body { font-size: (@font-size + 2)/@em; }
2 |
3 | #hohContainer,
4 | #heading { width: 1440px; }
5 |
6 | #heading { margin: 100px auto; }
7 |
8 | #circleBg {
9 | height: 30px;
10 | width: 30px;
11 | }
12 |
13 | #mapAndControls,
14 | #controls,
15 | #items,
16 | #itemDetail { width: 1300px; }
17 |
18 | #mapCanvas {
19 | height: 600px;
20 | width: 1300px;
21 | }
22 |
23 | #controls {
24 | #startDate,
25 | #endDate { width: 320px; }
26 | }
27 |
28 | #hideItemDetail { right: 1297px; }
--------------------------------------------------------------------------------
/app/less/size_640.less:
--------------------------------------------------------------------------------
1 | // Sort form baseline alignment on mobile
2 | input[type="submit"],
3 | input[type="reset"],
4 | html input[type="button"],
5 | button,
6 | a.button { line-height: 1.278; }
7 |
8 | #hohContainer,
9 | #heading { width: 300px; }
10 |
11 | #heading { margin: 40px auto 150px }
12 |
13 | #main_header {
14 | margin: 0 auto;
15 | width: 280px;
16 | }
17 |
18 | #circleBg {
19 | height: 30px;
20 | width: 30px;
21 |
22 | .fa-share-alt-square { font-size: 2.7em; }
23 | }
24 |
25 | #mapAndControls,
26 | #controls,
27 | #items,
28 | #itemDetail { width: 285px; }
29 |
30 | #mapCanvas {
31 | height: 250px;
32 | width: 285px;
33 | }
34 |
35 | #controls {
36 | .panel { padding: 0; }
37 |
38 | #startDate,
39 | #endDate { width: 72px; }
40 | }
41 |
42 | #hideItemDetail {
43 | height: 28px;
44 | right: 283px;
45 | width: 28px;
46 | }
--------------------------------------------------------------------------------
/app/less/size_640_800.less:
--------------------------------------------------------------------------------
1 | #hohContainer,
2 | #heading { width: 540px; }
3 |
4 | #heading { margin: 40px auto 80px }
5 |
6 | #main_header {
7 | margin: 0 auto;
8 | width: 480px;
9 | }
10 |
11 | #circleBg {
12 | height: 30px;
13 | width: 30px;
14 |
15 | .fa-share-alt-square { font-size: 2.7em; }
16 | }
17 |
18 | #mapAndControls,
19 | #controls,
20 | #items,
21 | #itemDetail { width: 425px; }
22 |
23 | #mapCanvas {
24 | height: 325px;
25 | width: 425px;
26 | }
27 |
28 | #controls {
29 | #startDate,
30 | #endDate { width: 100px; }
31 | }
32 |
33 | #hideItemDetail { right: 423px; }
--------------------------------------------------------------------------------
/app/less/size_640_up.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwatsonwailes/history-of-humanity/d8867d65a248c4711059dba62b56fab14cf79a13/app/less/size_640_up.less
--------------------------------------------------------------------------------
/app/less/size_800.less:
--------------------------------------------------------------------------------
1 | body { font-size: (@font-size - 2)/@em; }
2 |
3 | #heading h1 {
4 | margin-bottom: 1em;
5 | margin-top: 70px;
6 |
7 | #lower_title {
8 | line-height: 0;
9 | top: 0;
10 | }
11 | }
--------------------------------------------------------------------------------
/app/less/size_800_1024.less:
--------------------------------------------------------------------------------
1 | #hohContainer,
2 | #heading { width: 740px; }
3 |
4 | #heading { margin: 40px auto 80px }
5 |
6 | #main_header {
7 | margin: 0 auto;
8 | width: 680px;
9 | }
10 |
11 | #circleBg {
12 | height: 30px;
13 | width: 30px;
14 |
15 | .fa-share-alt-square { font-size: 2.3em; }
16 | }
17 |
18 | #mapAndControls,
19 | #controls,
20 | #items,
21 | #itemDetail { width: 625px; }
22 |
23 | #mapCanvas {
24 | height: 455px;
25 | width: 625px;
26 | }
27 |
28 | #controls {
29 | #startDate,
30 | #endDate { width: 130px; }
31 | }
32 |
33 | #hideItemDetail {
34 | height: 28px;
35 | line-height: 1.6;
36 | right: 623px;
37 | width: 28px;
38 | }
--------------------------------------------------------------------------------
/app/less/size_800_up.less:
--------------------------------------------------------------------------------
1 | h1:first-child, h2:first-child, h3:first-child { margin-top: 0; }
2 |
3 |
--------------------------------------------------------------------------------
/app/less/style.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Other imports (FontAwesome etc, if used)
3 | */
4 |
5 | @import url(//fonts.googleapis.com/css?family=Amiri:400italic|Open+Sans:300|Crimson+Text);
6 | @import url(//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css);
7 |
8 |
9 | /*
10 | * Theme mixins
11 | */
12 |
13 | .odm-dropdown(@top: 0, @right: 0, @left: 0, @overflow-x: 'auto', @overflow-y: 'auto', @after-right: 0, @after-left: 0) {
14 | .transition(opacity 400ms cubic-bezier(0.23, 1, 0.32, 1) 0ms);
15 | left: @left;
16 | right: @right;
17 | top: @top;
18 | background: #fff;
19 | list-style-type: none;
20 | margin: 0;
21 | max-height: 0;
22 | opacity: 0;
23 | overflow: hidden;
24 | padding: 0;
25 | position: absolute;
26 | z-index: 100;
27 |
28 | li {
29 | background: #eaeaea;
30 | cursor: pointer;
31 | font-size: 13px;
32 | margin: 0 0 -1px;
33 | z-index: 101;
34 |
35 | &:hover { background-color: #fefeff; }
36 | &:first-child { border-top: none; }
37 |
38 | span,
39 | a {
40 | color: #aaa;
41 | display: block;
42 | padding: 10px 20px;
43 | z-index: 102;
44 | }
45 | }
46 |
47 | &:after,
48 | &:before {
49 | left: @after-left;
50 | right: @after-right;
51 | }
52 |
53 | &.active {
54 | opacity: 1;
55 | max-height: 400px;
56 | overflow-y: scroll;
57 |
58 | .viewport_container {
59 | height: 100%;
60 | overflow: hidden;
61 | position: relative;
62 | width: 100%;
63 |
64 | .viewport {
65 | bottom: 0;
66 | left: 0;
67 | overflow-x: @overflow-x;
68 | overflow-y: @overflow-y;
69 | position: absolute;
70 | right: -18px;
71 | top: 0;
72 | }
73 | }
74 | }
75 | }
76 |
77 |
78 | /*
79 | * Compiled overrides
80 | */
81 |
82 |
83 |
84 |
85 | /*
86 | * Main classes
87 | */
88 |
89 | .label {
90 | .border-radius(50%);
91 | box-sizing: border-box;
92 | background: #d12727;
93 | border: 2px solid #fff;
94 | cursor: pointer;
95 | height: 10px;
96 | width: 10px;
97 | }
98 |
99 |
100 | .slider {
101 | background-color: #b9b9b9;
102 | border-radius: 3px;
103 | display: inline-block;
104 | position: relative;
105 |
106 | .value {
107 | background-color: #00b5ff;
108 | border-radius: 3px;
109 | position: absolute;
110 | }
111 |
112 | .handle {
113 | height: 8px;
114 | position: absolute;
115 | width: 8px;
116 |
117 | &:after {
118 | content: '';
119 | display: block;
120 | position: relative;
121 | }
122 | }
123 | }
124 |
125 | .slider_x .handle:after,
126 | .slider_y .handle:after {
127 | .border-radius(50%);
128 | background-color: #00b5ff;
129 | border: 1px solid #00b5ff;
130 | height: 12px;
131 | width: 12px;
132 | }
133 |
134 | .slider_x {
135 | height: 3px;
136 |
137 | .handle {
138 | top: 0;
139 | height: 100%;
140 |
141 | &:after {
142 | top: -5px;
143 | left: -6px;
144 | }
145 | }
146 | }
147 |
148 | .slider_y {
149 | width: 3px;
150 |
151 | .handle {
152 | left: 0;
153 | width: 100%;
154 |
155 | &:after {
156 | top: -6px;
157 | left: -2px;
158 | }
159 | }
160 | }
161 |
162 | .slider_xy {
163 | background-color: #00b5ff;
164 | border-radius: 0;
165 | position: relative;
166 | height: 100%;
167 | width: 100%;
168 |
169 | .handle {
170 | position: absolute;
171 |
172 | &:after {
173 | position: relative;
174 | display: block;
175 | top: -4px;
176 | left: -4px;
177 | width: 8px;
178 | height: 8px;
179 | background-color: rgba(0, 0, 0, 0);
180 | border: 2px solid #fff;
181 | border-radius: 50%;
182 | content: '';
183 | }
184 | }
185 | }
186 |
187 | .dropdown { .odm-dropdown() }
188 |
189 | /*
190 | * Size-agnostic layout rules
191 | */
192 |
193 | @import "size_0.less";
194 |
195 |
196 | /*
197 | Small
198 | */
199 |
200 | @media screen and (max-width: 639px) { @import "size_640.less"; }
201 | @media screen and (min-width: 640px) { @import "size_640_up.less"; }
202 |
203 | @media screen and (max-width: 799px) { @import "size_800.less"; }
204 | @media screen and (min-width: 800px) { @import "size_800_up.less"; }
205 |
206 | @media screen and (min-width: 640px) and (max-width: 799px) { @import "size_640_800.less"; }
207 |
208 | /*
209 | Mid
210 | */
211 |
212 | @media screen and (max-width: 1023px) { @import "size_1024.less"; }
213 | @media screen and (min-width: 1024px) { @import "size_1024_up.less"; }
214 |
215 | @media screen and (max-width: 1375px) { @import "size_1376.less"; }
216 | @media screen and (min-width: 1376px) { @import "size_1376_up.less"; }
217 |
218 | @media screen and (min-width: 800px) and (max-width: 1023px) { @import "size_800_1024.less"; }
219 | @media screen and (min-width: 1024px) and (max-width: 1375px) { @import "size_1024_1376.less"; }
220 |
221 | /*
222 | Large
223 | */
224 |
225 | @media screen and (min-width: 1376px) and (max-width: 1839px) { @import "size_1376_1840.less"; }
226 |
227 | @media screen and (max-width: 1839px) { @import "size_1840.less"; }
228 | @media screen and (min-width: 1840px) { @import "size_1840_up.less"; }
229 |
--------------------------------------------------------------------------------
/app/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import axios from 'axios';
4 | import TimelineData from './data/timeline.json';
5 | import HoH from './js/dispatcher.js';
6 |
7 | window.app = (function() {
8 | var requiredFeatures = {
9 | "JSON decoding": window.JSON,
10 | "the selectors API": document.querySelector,
11 | "DOM level 2 events": window.addEventListener,
12 | "the HTML5 history API": window.history.pushState
13 | };
14 |
15 | for (var i = requiredFeatures.length - 1; i >= 0; i--) {
16 | if (!requiredFeatures[i])
17 | return alert("Sorry, but your browser does not support " + feature + " so this app won't work properly.");
18 | };
19 |
20 | if (String(window.location.pathname).match(/\/history-of-humanity\/\d+\/\d+\/.+/i) !== null) {
21 | var parts = window.location.pathname.replace('/history-of-humanity/', '').split('/');
22 | var params = { pointer: 0, year: parts[0], position: parts[1], name: parts[2] };
23 |
24 | var initData = {
25 | itemDetail: TimelineData[params.year][params.position],
26 | wikiData: false,
27 | wikiImages: []
28 | };
29 |
30 | var wikiApiLink = 'https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|images&exintro=&explaintext=&titles=' + params.name;
31 |
32 | axios.get('https://wail.es/history/api.php?url=' + encodeURIComponent(wikiApiLink.replace(/&/g, "&"))).then(function (output) {
33 | if (isset(output.data.query.pages)) {
34 | var pageId = Object.keys(output.data.query.pages);
35 | initData.wikiData = output.data.query.pages[pageId];
36 |
37 | // React.renderToString takes your component and generates rendered markup. SEO friendliness all the way
38 | return ReactDOM.render(React.createElement(HoH, { timeline: TimelineData, initparams: params, initwikidata: initData }), document.getElementById('hoh'));
39 | }
40 | })
41 | .catch(function (e) {
42 | console.log('error in xhr');
43 | console.log(e);
44 | });
45 | }
46 | else if (String(window.location.pathname).match(/\/history-of-humanity\/p\/\d+/i) !== null) {
47 | var parts = window.location.pathname.replace('/history-of-humanity/', '').split('/');
48 |
49 | if (parseInt(parts[1]) > 0)
50 | return ReactDOM.render(React.createElement(HoH, { timeline: TimelineData, initparams: { pointer: parseInt(parts[1]) - 1, year: false, position: false, name: false } }), document.getElementById('hoh'));
51 | else
52 | window.location.replace("https://wail.es/history-of-humanity/");
53 | }
54 | else {
55 | return ReactDOM.render(React.createElement(HoH, { timeline: TimelineData, initparams: { pointer: 0, year: false, position: false, name: false } }), document.getElementById('hoh'));
56 | }
57 | })();
--------------------------------------------------------------------------------
/app/routes/core-routes.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOMServer from 'react-dom/server';
3 | import TimelineData from '../data/timeline.json';
4 | import axios from 'axios';
5 | import HoH from '../js/dispatcher.js';
6 |
7 | // React.renderToString takes your component and generates rendered markup. SEO friendliness all the way
8 | module.exports = function(app) {
9 | app.get('/', function(req, res) {
10 | res.render('index.ejs', {
11 | reactTitle: '',
12 | reactPath: '',
13 | reactOutput: ReactDOMServer.renderToString(React.createElement(HoH, {
14 | timeline: TimelineData,
15 | initparams: { pointer: 0 }
16 | }))
17 | });
18 | });
19 |
20 | app.get('/p/:n', function(req, res) {
21 | if (req.params.n > 0) {
22 | res.render('index.ejs', {
23 | reactTitle: 'Page ' + req.params.n + ' | ',
24 | reactPath: 'p/' + req.params.n,
25 | reactOutput: ReactDOMServer.renderToString(React.createElement(HoH, {
26 | timeline: TimelineData,
27 | initparams: { pointer: req.params.n - 1 }
28 | }))
29 | });
30 | }
31 | else
32 | res.redirect(301, 'https://wail.es/history-of-humanity/')
33 | });
34 |
35 | app.get('/:year/:position/:name', function(req, res) {
36 | var initData = {
37 | itemDetail: TimelineData[req.params.year][req.params.position],
38 | wikiData: false,
39 | wikiImages: []
40 | };
41 |
42 | var wikiApiLink = 'https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|images&exintro=&explaintext=&titles=' + req.params.name;
43 |
44 | axios.get('https://wail.es/history/api.php?url=' + encodeURIComponent(wikiApiLink.replace(/&/g, "&"))).then(function (output) {
45 | if (typeof output.data.query.pages !== 'undefined') {
46 | var pageId = Object.keys(output.data.query.pages);
47 | initData.wikiData = output.data.query.pages[pageId];
48 |
49 | res.render('index.ejs', {
50 | reactTitle: initData.itemDetail.text + ' | ',
51 | reactPath: req.params.year + '/' + req.params.position + '/' + req.params.name,
52 | reactOutput: ReactDOMServer.renderToString(React.createElement(HoH, {
53 | timeline: TimelineData,
54 | initparams: req.params,
55 | initwikidata: initData
56 | }))
57 | });
58 | }
59 | })
60 | .catch(function (e) {
61 | console.log('error in xhr');
62 | console.log(e);
63 | })
64 | })
65 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "history-of-humanity",
3 | "version": "0.1.0",
4 | "description": "A wikipedia powered React.JS demo application",
5 | "main": "server.js",
6 | "scripts": {
7 | "build-dev": "browserify app/main.js -o public/bundle.dev.js -t [ babelify --presets [ es2015 react stage-1 ] ]",
8 | "build-min": "browserify app/main.js -g uglifyify -o public/bundle.min.js -t [ babelify --presets [ es2015 react stage-1 ] ]",
9 | "build-server": "babel server.js -d serer.min.js --presets babel-preset-es2015 babel-preset-react",
10 | "start": "node server.js"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/pwatsonwailes/history-of-humanity.git"
15 | },
16 | "author": "petewailes",
17 | "license": "BSD-3-Clause",
18 | "bugs": {
19 | "url": "https://github.com/pwatsonwailes/history-of-humanity/issues"
20 | },
21 | "homepage": "https://github.com/pwatsonwailes/history-of-humanity",
22 | "devDependencies": {
23 | "browserify": "^12.x.x",
24 | "uglifyify": "3.0.x"
25 | },
26 | "dependencies": {
27 | "axios": "^0.5.4",
28 | "babel": "^6.x.x",
29 | "babel-core": "^6.1.2",
30 | "babel-preset-es2015": "^6.x.x",
31 | "babel-preset-react": "^6.x.x",
32 | "babel-preset-stage-1": "^6.x.x",
33 | "babelify": "^7.2.0",
34 | "body-parser": "^1.13.3",
35 | "ejs": "^2.3.3",
36 | "express": "^4.13.3",
37 | "react": "^0.14.2",
38 | "react-addons-css-transition-group": "^0.14.2",
39 | "react-dom": "^0.14.2"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/public/compiled.css:
--------------------------------------------------------------------------------
1 | @import url(//fonts.googleapis.com/css?family=Amiri:400italic|Open+Sans:300|Crimson+Text);@import url(//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css);article,aside,details,dialog,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}a,a img,blink,img,ins,mark{text-decoration:none}a img,img{-ms-interpolation-mode:bicubic}#heading h1 #lower_title,#heading p{font-family:Amiri}b,caption,dt,form label,legend,strong,th,thead{font-weight:700}#controls:after,#heading h1,#heading:after,#hohContainer:after,#itemDetail:after,#items:after,#mapAndControls:after,#socialButtons #socialIcons:after,.clearfix:after,.inline-scroll:after,.inline:after,.od-clear,.pagination:after,.paginator:after,.row:after{clear:both}a,abbr,acronym,address,article,aside,audio,b,big,blockquote,body,caption,cite,code,dd,del,dfn,dialog,div,dl,dt,em,fieldset,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,samp,section,small,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,ul,var,video{background:0 0;border:0;font-family:inherit;font-size:100%;font-weight:inherit;font-style:inherit;margin:0;outline:0;padding:0;text-align:left;vertical-align:baseline;white-space:normal}#heading h1 #lower_title,#heading p,cite,dfn,em,i{font-style:italic}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}applet,basefont,dir,font,isindex,menu,s,strike,u{border:0;color:inherit;font-family:inherit;font-size:100%;font-weight:400;font-style:normal;margin:0;outline:0;padding:0;text-decoration:inherit;text-align:left;vertical-align:baseline;white-space:normal}dir,menu{list-style:none}nobr{white-space:normal}marquee{overflow:visible}.inline,.inline-scroll{overflow:hidden;list-style-type:none}html{font-family:sans-serif;height:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{color:#313131;font-size:100%;line-height:1.5;min-height:100%;-webkit-tap-highlight-color:rgba(255,0,0,.62)}mark{padding:0 .25em}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}.test{background:#edd}h1{font-size:3.75em;line-height:1.2em;margin-bottom:.4em}h2{font-size:3em;line-height:1em;margin-bottom:.5em}h3{font-size:2.25em;line-height:1.3333333333333333333333333333333em;margin-bottom:.6667em}h4{font-size:1.5em;line-height:1em;margin-bottom:1em}h5{font-size:1.3125em;line-height:1.1428571428571428571428571428571em;margin-bottom:1.14285714em}h6{font-size:1.125em;line-height:1.3333333333333333333333333333333em;margin-bottom:1.33333333em}address,blockquote,code,dialog,dl,label,ol,p,pre,td,th,ul{display:block;font-size:1em;line-height:1.6em;margin-bottom:1.6em}p.small,small{font-size:80%;line-height:1.2;margin:0}dialog,dl,dl dd,ol,ul{margin-left:1.6em}a{color:#0049cc}a:hover{color:#0bcdd9}a:focus{outline:dotted thin}a:active,a:hover{outline:0}a img,img{border:0}hr{margin:0 0 1.375em;padding:0}address,var{font-style:normal}p code,p pre,p var{line-height:1.2em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}dialog,dl,ol,ul{list-style:none inside;padding:0}ul{list-style:disc}ol{list-style:decimal}.inline li,.inline-scroll li,.pagination li,.paginator li{list-style:none}li{font-size:1em;margin-bottom:1em}li label,li:last-child{margin-bottom:0}li ol,li ul{margin:1em 1.6em 0}li ul{list-style-type:circle}li ol{list-style-type:lower-alpha}.inline,nav ul li{margin-left:0}.unstyled-list{list-style-type:none;margin-left:0;padding:0}.unstyled-list li{display:block;list-style:none}.inline{padding:0}.inline:after,.inline:before{content:"";display:table}.inline li{display:inline-block;margin:0}.inline li:before{content:"";margin:0 .66667em;position:relative;top:1px}.inline li:first-child:before,.inline.no-margin li:before{margin:0}.inline li form,.inline li input{margin-bottom:0}.inline.breadcrumbs li:before{content:"/"}.inline-scroll li:before,.inline-scroll:after,.inline-scroll:before,.pagination li:before,.pagination:after,.pagination:before,.paginator li:before,.paginator:after,.paginator:before{content:""}.inline.breadcrumbs li.inline:first-child:before{content:"";margin:0}.inline.li-margin li{margin-left:.66667em}.inline.li-margin li:before,.inline.li-margin li:first-child{margin:0}.inline .radius>:first-child,.inline .radius>:first-child>.button,.inline .radius>:first-child>a,.inline .radius>:first-child>button{-webkit-border-bottom-left-radius:5px;-moz-border-radius-bottomleft:5px;border-bottom-left-radius:5px;-webkit-border-top-left-radius:5px;-webkit-background-clip:padding-box;-moz-border-radius-topleft:5px;-moz-background-clip:padding;border-top-left-radius:5px;background-clip:padding-box}.inline .radius>:last-child,.inline .radius>:last-child>.button,.inline .radius>:last-child>a,.inline .radius>:last-child>button{-webkit-border-bottom-right-radius:5px;-moz-border-radius-bottomright:5px;border-bottom-right-radius:5px;-webkit-border-top-right-radius:5px;-webkit-background-clip:padding-box;-moz-border-radius-topright:5px;-moz-background-clip:padding;border-top-right-radius:5px;background-clip:padding-box}.inline-scroll{margin-left:0;padding:0;overflow-x:auto;white-space:nowrap}.dropdown,.pagination,svg:not(:root){overflow:hidden}.inline-scroll:after,.inline-scroll:before{display:table}.inline-scroll li{display:inline-block;margin:0}.inline-scroll li:before{margin:0 .66667em;position:relative;top:1px}.inline-scroll li:first-child:before{margin:0}.inline-scroll li form,.inline-scroll li input{margin-bottom:0}.pagination{list-style-type:none;margin-left:0;padding:0}.pagination:after,.pagination:before{display:table}.pagination li{display:inline-block;margin:0}.pagination li:before{margin:0 .66667em;position:relative;top:1px}.pagination li:first-child:before{margin:0}.pagination li form,.pagination li input{margin-bottom:0}.pagination li{margin-left:.25em}.pagination li:hover a{background:#eee}.pagination li a{-webkit-border-radius:5px;-webkit-background-clip:padding-box;-moz-border-radius:5px;-moz-background-clip:padding;border-radius:5px;background-clip:padding-box;-webkit-transition:background-color .3s ease-out;-moz-transition:background-color .3s ease-out;-o-transition:background-color .3s ease-out;transition:background-color .3s ease-out;display:block;padding:.1em .75rem}.pagination li a.selected{background:#0049cc;color:#fff;cursor:default;font-weight:700}blockquote,cite,q{font-style:italic quotes: none}blockquote:after,blockquote:before,q:after,q:before{content:'';content:none}blockquote{border-left:3px solid #dfdfdf;padding-left:1.6em}blockquote>p{padding:0}abbr,acronym,dfn{font-size:80%;letter-spacing:.1em;line-height:1.2;text-transform:uppercase}abbr[title],acronym[title],dfn[title]{border-bottom:1px dotted #000;cursor:help}ins{color:red}del{text-decoration:line-through}mark{background:#c47529;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.7em}sub{bottom:-.25em}embed,img,object,video{max-width:100%}img{border:0}img::selection{background:0 0}img::-moz-selection{background:0 0}img.no-max{max-width:none}figure,form label,table{max-width:100%}figure{margin:0 0 1.6em}figure img{height:auto;width:100%}figure figcaption{background:#eee;border-left:5px solid #999;margin-bottom:0;padding:.4em .8em}::-moz-selection,::selection{background:#c47529;color:#fff;text-shadow:none}table{border-collapse:collapse;border-spacing:0;margin-bottom:1.6em;width:100%}table .striped>tbody>tr:nth-child(odd)>td{background:#f0f0f0}tr{display:table-row}tr .success td{background-color:#2ecc71}tr .success-dark td{background-color:#27ad60}tr .info td{background-color:#3498db}tr .info-dark td{background-color:#2383c4}tr .warning td{background-color:#f1c40f}tr .warning-dark td{background-color:#cea70c}tr .danger td{background-color:#e74c3c}tr .danger-dark td{background-color:#dc2d1b}td,th{display:table-cell;padding:8px}th{border-bottom:2px solid #ddd;border-top:0;vertical-align:bottom}td{border-top:1px solid #ddd;vertical-align:top}form{border-bottom:1px solid rgba(0,0,0,.1);margin-bottom:20px;padding:0 0 1pc}form fieldset{border:0;margin:0;min-width:0;padding:0}form fieldset legend{border:0;border-bottom:1px solid #e5e5e5;display:block;font-size:19.2px;padding:0;width:100%}form label{display:inline-block;font-family:inherit;margin-bottom:8px}form label.firm{color:#1abc9c}form label.success{color:#11b452}form label.info{color:#3498db}form label.warning{color:#f1c40f}form label.danger{color:#e74c3c}form label.night{color:#34495e}form input[type=email],form input[type=number],form input[type=password],form input[type=text],form textarea{-webkit-box-shadow:inset 0 -1px 0 #ddd;-moz-box-shadow:inset 0 -1px 0 #ddd;box-shadow:inset 0 -1px 0 #ddd;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-moz-transition:border-color ease-in-out .15s,-moz-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;background:0 0;border:none;color:#666;font-size:1pc;display:block;min-height:26px;line-height:26px;padding:0;width:100%}form input[type=email]:focus,form input[type=number]:focus,form input[type=password]:focus,form input[type=text]:focus,form textarea:focus{-webkit-box-shadow:inset 0 -2px 0 #2196f3;-moz-box-shadow:inset 0 -2px 0 #2196f3;box-shadow:inset 0 -2px 0 #2196f3;border-color:#66AFE9;outline:0}form input[type=email].firm,form input[type=number].firm,form input[type=password].firm,form input[type=text].firm,form textarea.firm{border-color:#1abc9c}form input[type=email].success,form input[type=number].success,form input[type=password].success,form input[type=text].success,form textarea.success{border-color:#11b452}form input[type=email].info,form input[type=number].info,form input[type=password].info,form input[type=text].info,form textarea.info{border-color:#3498db}form input[type=email].warning,form input[type=number].warning,form input[type=password].warning,form input[type=text].warning,form textarea.warning{border-color:#f1c40f}form input[type=email].danger,form input[type=number].danger,form input[type=password].danger,form input[type=text].danger,form textarea.danger{border-color:#e74c3c}form select[multiple],form select[size],form textarea{height:auto}form select{-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-moz-transition:border-color ease-in-out .15s,-moz-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;background-color:#fff;border:1px solid #ccc;font-size:1pc;line-height:26px;margin:0;padding:.3em .2em;position:relative;top:-4px;width:100%}form select:focus{border-color:#66AFE9;outline:0}form.no-border{border-bottom:none}form .input-row{padding-left:13px;padding-right:13px;margin-bottom:1pc;position:relative}form .input-group{border-collapse:separate;display:table;position:relative}form .input-group .addon,form .input-group .button,form .input-group .input{display:table-cell}form .input-group .addon,form .input-group .button{padding:0 1pc;vertical-align:middle;white-space:nowrap;width:1%}form .input-group .button{font-size:0;position:relative;white-space:nowrap}form .input-group .input{float:left;margin-bottom:0;position:relative;width:100%;z-index:2}a.button,form button,form input[type=submit],form input[type=reset],html input[type=button]{-webkit-border-radius:5px;-webkit-background-clip:padding-box;-moz-border-radius:5px;-moz-background-clip:padding;border-radius:5px;-webkit-transition:all .2s;-moz-transition:all .2s;-o-transition:all .2s;transition:all .2s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:#fff;border:none;color:#666;cursor:pointer;display:inline-block;font-size:12.8px;font-weight:400;line-height:20.8px;letter-spacing:.1px;margin:0;padding:7px 1pc;position:relative;text-align:center;text-rendering:optimizeLegibility;text-transform:uppercase;top:-7px;vertical-align:middle;white-space:nowrap;-webkit-font-smoothing:antialiased}a.button:hover,form button:hover,form input[type=submit]:hover,form input[type=reset]:hover,html input[type=button]:hover{-webkit-box-shadow:0 3px 6px rgba(0,0,0,.2),0 3px 6px rgba(0,0,0,.28);-moz-box-shadow:0 3px 6px rgba(0,0,0,.2),0 3px 6px rgba(0,0,0,.28);box-shadow:0 3px 6px rgba(0,0,0,.2),0 3px 6px rgba(0,0,0,.28)}a.button.success,form button.success,form input[type=submit].success,form input[type=reset].success,html input[type=button].success{background:#11b452}a.button.success:active,form button.success:active,form input[type=submit].success:active,form input[type=reset].success:active,html input[type=button].success:active{background:#27ad60}a.button.info,form button.info,form input[type=submit].info,form input[type=reset].info,html input[type=button].info{background:#3498db}a.button.info:active,form button.info:active,form input[type=submit].info:active,form input[type=reset].info:active,html input[type=button].info:active{background:#2383c4}a.button.warning,form button.warning,form input[type=submit].warning,form input[type=reset].warning,html input[type=button].warning{background:#f1c40f}a.button.warning:active,form button.warning:active,form input[type=submit].warning:active,form input[type=reset].warning:active,html input[type=button].warning:active{background:#cea70c}a.button.danger,form button.danger,form input[type=submit].danger,form input[type=reset].danger,html input[type=button].danger{background:#e74c3c}a.button.danger:active,form button.danger:active,form input[type=submit].danger:active,form input[type=reset].danger:active,html input[type=button].danger:active{background:#dc2d1b}a.button.submit,form button.submit,form input[type=submit].submit,form input[type=reset].submit,html input[type=button].submit{background:#2196f3;color:#fff}a.button.submit:active,form button.submit:active,form input[type=submit].submit:active,form input[type=reset].submit:active,html input[type=button].submit:active{background:#285e8e}[hidden]{display:none}[disabled]{cursor:default}:focus{outline:0}.clearfix:after,.clearfix:before{content:" ";display:table}.row{display:block;margin:0 auto;padding:0}.row:after,.row:before{content:" ";display:table}#bg:after,.slider .handle:after,.slider_xy .handle:after{content:''}.row .row{width:auto}.row .row.collapse{margin:0}.col{float:left;min-height:1px;position:relative;padding-left:13px;padding-right:13px}.col-no-gutter{float:left;min-height:1px;position:relative}.col-left-gutter{float:left;min-height:1px;position:relative;padding-left:26px}.col-right-gutter{float:left;min-height:1px;position:relative;padding-right:26px}.col-inverse,.col-left-gutter-inverse,.col-no-gutter-inverse,.col-right-gutter-inverse{float:right;min-height:1px;position:relative}.col-inverse{padding-left:13px;padding-right:13px}.col-left-gutter-inverse{padding-left:26px}.col-right-gutter-inverse{padding-right:26px}.col-inverse-no-gutter.width-1,.col-inverse.width-1,.col-no-gutter.width-1,.col.width-1{width:8.33333%}.col-inverse-no-gutter.width-2,.col-inverse.width-2,.col-no-gutter.width-2,.col.width-2{width:16.66667%}.col-inverse-no-gutter.width-3,.col-inverse.width-3,.col-no-gutter.width-3,.col.width-3{width:25%}.col-inverse-no-gutter.width-4,.col-inverse.width-4,.col-no-gutter.width-4,.col.width-4{width:33.33333%}.col-inverse-no-gutter.width-5,.col-inverse.width-5,.col-no-gutter.width-5,.col.width-5{width:41.66667%}.col-inverse-no-gutter.width-6,.col-inverse.width-6,.col-no-gutter.width-6,.col.width-6{width:50%}.col-inverse-no-gutter.width-7,.col-inverse.width-7,.col-no-gutter.width-7,.col.width-7{width:58.33333%}.col-inverse-no-gutter.width-8,.col-inverse.width-8,.col-no-gutter.width-8,.col.width-8{width:66.66667%}.col-inverse-no-gutter.width-9,.col-inverse.width-9,.col-no-gutter.width-9,.col.width-9{width:75%}.col-inverse-no-gutter.width-10,.col-inverse.width-10,.col-no-gutter.width-10,.col.width-10{width:83.33333%}.col-inverse-no-gutter.width-11,.col-inverse.width-11,.col-no-gutter.width-11,.col.width-11{width:91.66667%}.col-inverse-no-gutter.width-12,.col-inverse.width-12,.col-no-gutter.width-12,.col.width-12{width:100%}@media screen and (max-width:799px){.col-inverse-no-gutter.width-13,.col-inverse-no-gutter.width-14,.col-inverse-no-gutter.width-15,.col-inverse-no-gutter.width-16,.col-inverse-no-gutter.width-17,.col-inverse-no-gutter.width-18,.col-inverse-no-gutter.width-19,.col-inverse-no-gutter.width-20,.col-inverse-no-gutter.width-21,.col-inverse-no-gutter.width-22,.col-inverse-no-gutter.width-23,.col-inverse-no-gutter.width-24,.col-inverse.width-13,.col-inverse.width-14,.col-inverse.width-15,.col-inverse.width-16,.col-inverse.width-17,.col-inverse.width-18,.col-inverse.width-19,.col-inverse.width-20,.col-inverse.width-21,.col-inverse.width-22,.col-inverse.width-23,.col-inverse.width-24,.col-no-gutter.width-13,.col-no-gutter.width-14,.col-no-gutter.width-15,.col-no-gutter.width-16,.col-no-gutter.width-17,.col-no-gutter.width-18,.col-no-gutter.width-19,.col-no-gutter.width-20,.col-no-gutter.width-21,.col-no-gutter.width-22,.col-no-gutter.width-23,.col-no-gutter.width-24,.col.width-13,.col.width-14,.col.width-15,.col.width-16,.col.width-17,.col.width-18,.col.width-19,.col.width-20,.col.width-21,.col.width-22,.col.width-23,.col.width-24{width:100%}}@media screen and (min-width:800px){.col-inverse-no-gutter.width-13,.col-inverse.width-13,.col-no-gutter.width-13,.col.width-13{width:108.33333%}.col-inverse-no-gutter.width-14,.col-inverse.width-14,.col-no-gutter.width-14,.col.width-14{width:116.66667%}.col-inverse-no-gutter.width-15,.col-inverse.width-15,.col-no-gutter.width-15,.col.width-15{width:125%}.col-inverse-no-gutter.width-16,.col-inverse.width-16,.col-no-gutter.width-16,.col.width-16{width:133.33333%}.col-inverse-no-gutter.width-17,.col-inverse.width-17,.col-no-gutter.width-17,.col.width-17{width:141.66667%}.col-inverse-no-gutter.width-18,.col-inverse.width-18,.col-no-gutter.width-18,.col.width-18{width:150%}.col-inverse-no-gutter.width-19,.col-inverse.width-19,.col-no-gutter.width-19,.col.width-19{width:158.33333%}.col-inverse-no-gutter.width-20,.col-inverse.width-20,.col-no-gutter.width-20,.col.width-20{width:166.66667%}.col-inverse-no-gutter.width-21,.col-inverse.width-21,.col-no-gutter.width-21,.col.width-21{width:175%}.col-inverse-no-gutter.width-22,.col-inverse.width-22,.col-no-gutter.width-22,.col.width-22{width:183.33333%}.col-inverse-no-gutter.width-23,.col-inverse.width-23,.col-no-gutter.width-23,.col.width-23{width:191.66667%}.col-inverse-no-gutter.width-24,.col-inverse.width-24,.col-no-gutter.width-24,.col.width-24{width:200%}.col-inverse-no-gutter.width-offset-0,.col-inverse.width-offset-0,.col-no-gutter.width-offset-0,.col.width-offset-0{margin-left:0}.col-inverse-no-gutter.width-offset-1,.col-inverse.width-offset-1,.col-no-gutter.width-offset-1,.col.width-offset-1{margin-left:8.33333%}.col-inverse-no-gutter.width-offset-2,.col-inverse.width-offset-2,.col-no-gutter.width-offset-2,.col.width-offset-2{margin-left:16.66667%}.col-inverse-no-gutter.width-offset-3,.col-inverse.width-offset-3,.col-no-gutter.width-offset-3,.col.width-offset-3{margin-left:25%}.col-inverse-no-gutter.width-offset-4,.col-inverse.width-offset-4,.col-no-gutter.width-offset-4,.col.width-offset-4{margin-left:33.33333%}.col-inverse-no-gutter.width-offset-5,.col-inverse.width-offset-5,.col-no-gutter.width-offset-5,.col.width-offset-5{margin-left:41.66667%}.col-inverse-no-gutter.width-offset-6,.col-inverse.width-offset-6,.col-no-gutter.width-offset-6,.col.width-offset-6{margin-left:50%}.col-inverse-no-gutter.width-offset-7,.col-inverse.width-offset-7,.col-no-gutter.width-offset-7,.col.width-offset-7{margin-left:58.33333%}.col-inverse-no-gutter.width-offset-8,.col-inverse.width-offset-8,.col-no-gutter.width-offset-8,.col.width-offset-8{margin-left:66.66667%}.col-inverse-no-gutter.width-offset-9,.col-inverse.width-offset-9,.col-no-gutter.width-offset-9,.col.width-offset-9{margin-left:75%}.col-inverse-no-gutter.width-offset-10,.col-inverse.width-offset-10,.col-no-gutter.width-offset-10,.col.width-offset-10{margin-left:83.33333%}.col-inverse-no-gutter.push,.col-inverse.push,.col-no-gutter.push,.col.push{right:auto}.col-inverse-no-gutter.pull,.col-inverse.pull,.col-no-gutter.pull,.col.pull{left:auto}.col-inverse-no-gutter.push-1,.col-inverse.push-1,.col-no-gutter.push-1,.col.push-1{margin-left:-8.33333%;left:8.33333%}.col-inverse-no-gutter.push-2,.col-inverse.push-2,.col-no-gutter.push-2,.col.push-2{margin-left:-16.66667%;left:16.66667%}.col-inverse-no-gutter.push-3,.col-inverse.push-3,.col-no-gutter.push-3,.col.push-3{margin-left:-25%;left:25%}.col-inverse-no-gutter.push-4,.col-inverse.push-4,.col-no-gutter.push-4,.col.push-4{margin-left:-33.33333%;left:33.33333%}.col-inverse-no-gutter.push-5,.col-inverse.push-5,.col-no-gutter.push-5,.col.push-5{margin-left:-41.66667%;left:41.66667%}.col-inverse-no-gutter.push-6,.col-inverse.push-6,.col-no-gutter.push-6,.col.push-6{margin-left:-50%;left:50%}.col-inverse-no-gutter.push-7,.col-inverse.push-7,.col-no-gutter.push-7,.col.push-7{margin-left:-58.33333%;left:58.33333%}.col-inverse-no-gutter.push-8,.col-inverse.push-8,.col-no-gutter.push-8,.col.push-8{margin-left:-66.66667%;left:66.66667%}.col-inverse-no-gutter.push-9,.col-inverse.push-9,.col-no-gutter.push-9,.col.push-9{margin-left:-75%;left:75%}.col-inverse-no-gutter.push-10,.col-inverse.push-10,.col-no-gutter.push-10,.col.push-10{margin-left:-83.33333%;left:83.33333%}.col-inverse-no-gutter.push-11,.col-inverse.push-11,.col-no-gutter.push-11,.col.push-11{margin-left:-91.66667%;left:91.66667%}.col-inverse-no-gutter.pull-1,.col-inverse.pull-1,.col-no-gutter.pull-1,.col.pull-1{margin-right:-8.33333%;right:8.33333%}.col-inverse-no-gutter.pull-2,.col-inverse.pull-2,.col-no-gutter.pull-2,.col.pull-2{margin-right:-16.66667%;right:16.66667%}.col-inverse-no-gutter.pull-3,.col-inverse.pull-3,.col-no-gutter.pull-3,.col.pull-3{margin-right:-25%;right:25%}.col-inverse-no-gutter.pull-4,.col-inverse.pull-4,.col-no-gutter.pull-4,.col.pull-4{margin-right:-33.33333%;right:33.33333%}.col-inverse-no-gutter.pull-5,.col-inverse.pull-5,.col-no-gutter.pull-5,.col.pull-5{margin-right:-41.66667%;right:41.66667%}.col-inverse-no-gutter.pull-6,.col-inverse.pull-6,.col-no-gutter.pull-6,.col.pull-6{margin-right:-50%;right:50%}.col-inverse-no-gutter.pull-7,.col-inverse.pull-7,.col-no-gutter.pull-7,.col.pull-7{margin-right:-58.33333%;right:58.33333%}.col-inverse-no-gutter.pull-8,.col-inverse.pull-8,.col-no-gutter.pull-8,.col.pull-8{margin-right:-66.66667%;right:66.66667%}.col-inverse-no-gutter.pull-9,.col-inverse.pull-9,.col-no-gutter.pull-9,.col.pull-9{margin-right:-75%;right:75%}.col-inverse-no-gutter.pull-10,.col-inverse.pull-10,.col-no-gutter.pull-10,.col.pull-10{margin-right:-83.33333%;right:83.33333%}.col-inverse-no-gutter.pull-11,.col-inverse.pull-11,.col-no-gutter.pull-11,.col.pull-11{margin-right:-91.66667%;right:91.66667%}.col-inverse-no-gutter.centered,.col-inverse.centered,.col-no-gutter.centered,.col.centered{float:none;margin:0 auto}}.gutter{margin:13px}.gutter-horizontal{margin-left:13px;margin-right:13px}.gutter-vertical{margin-top:13px;margin-bottom:13px}.gutter-top{margin-top:26px}.gutter-right{margin-right:26px}.gutter-bottom{margin-bottom:26px}.gutter-left{margin-left:26px}.internal-gutter{padding:13px}.internal-gutter-horizontal{padding-left:13px;padding-right:13px}.internal-gutter-vertical{padding-top:13px;padding-bottom:13px}.internal-gutter-top{padding-top:26px}.internal-gutter-right{padding-right:26px}.internal-gutter-bottom{padding-bottom:26px}.internal-gutter-left{padding-left:26px}figure.col{padding-left:0}figure.col-inverse{padding-right:0}.download-modal,.info-modal,.modal,.note-modal,.warning-modal{-webkit-border-radius:5px;-webkit-background-clip:padding-box;-moz-border-radius:5px;-moz-background-clip:padding;border-radius:5px;-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);-moz-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5);background-clip:padding-box;background-color:#fff;border:1px solid transparent;outline:0;position:relative}.box,.label{-webkit-background-clip:padding-box;-moz-background-clip:padding}.download-modal .modal-body,.download-modal .modal-footer,.download-modal .modal-header,.info-modal .modal-body,.info-modal .modal-footer,.info-modal .modal-header,.modal .modal-body,.modal .modal-footer,.modal .modal-header,.note-modal .modal-body,.note-modal .modal-footer,.note-modal .modal-header,.warning-modal .modal-body,.warning-modal .modal-footer,.warning-modal .modal-header{padding:1pc}.download-modal .modal-header,.info-modal .modal-header,.modal .modal-header,.note-modal .modal-header,.warning-modal .modal-header{border-bottom:1px solid transparent;min-height:1pc}.download-modal .modal-body,.info-modal .modal-body,.modal .modal-body,.note-modal .modal-body,.warning-modal .modal-body{position:relative}.download-modal .modal-footer,.info-modal .modal-footer,.modal .modal-footer,.note-modal .modal-footer,.warning-modal .modal-footer{border-top:1px solid transparent;text-align:right;font-style:italic}.box{-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;background-clip:padding-box;background-color:#fff;border:1px solid transparent;outline:0;padding:5px;position:relative}.palette-success{background-color:#2ecc71}.palette-warning{background-color:#f1c40f}.palette-danger{background-color:#e74c3c}.palette-submit{background-color:#2196f3}.palette-success-dark{background-color:#27ad60;color:#fff}.palette-info{background-color:#dbc034;color:#fff}.palette-info-dark{background-color:#a88f0b;color:#fff}.palette-warning-dark{background-color:#cea70c;color:#fff}.palette-danger-dark{background-color:#dc2d1b;color:#fff}.palette-submit-dark{background-color:#285e8e;color:#fff}.label{-webkit-border-radius:50%;-moz-border-radius:50%;border-radius:50%;box-sizing:border-box;background:#d12727;border:2px solid #fff;cursor:pointer;height:10px;width:10px}.slider{background-color:#b9b9b9;border-radius:3px;display:inline-block;position:relative}.slider .value{background-color:#00b5ff;border-radius:3px;position:absolute}.slider .handle{height:8px;position:absolute;width:8px}.slider .handle:after{display:block;position:relative}.slider_x .handle:after,.slider_y .handle:after{-webkit-border-radius:50%;-webkit-background-clip:padding-box;-moz-border-radius:50%;-moz-background-clip:padding;border-radius:50%;background-clip:padding-box;background-color:#00b5ff;border:1px solid #00b5ff;height:9pt;width:9pt}.slider_x{height:3px}.slider_x .handle{top:0;height:100%}.slider_x .handle:after{top:-5px;left:-6px}.slider_y{width:3px}.slider_y .handle{left:0;width:100%}.slider_y .handle:after{top:-6px;left:-2px}.slider_xy{background-color:#00b5ff;border-radius:0;position:relative;height:100%;width:100%}.slider_xy .handle{position:absolute}.slider_xy .handle:after{position:relative;display:block;top:-4px;left:-4px;width:8px;height:8px;background-color:transparent;border:2px solid #fff;border-radius:50%}.dropdown{-webkit-transition:opacity .4s cubic-bezier(.23,1,.32,1) 0s;-moz-transition:opacity .4s cubic-bezier(.23,1,.32,1) 0s;-o-transition:opacity .4s cubic-bezier(.23,1,.32,1) 0s;transition:opacity .4s cubic-bezier(.23,1,.32,1) 0s;left:0;right:0;top:0;background:#fff;list-style-type:none;margin:0;max-height:0;opacity:0;padding:0;position:absolute;z-index:100}.dropdown li{background:#eaeaea;cursor:pointer;font-size:13px;margin:0 0 -1px;z-index:101}#socialButtons #circleBg,#socialButtons .share{-webkit-background-clip:padding-box;-moz-background-clip:padding}#controls p,#heading h1,#heading p:last-child{margin-bottom:0}.dropdown li:hover{background-color:#fefeff}.dropdown li:first-child{border-top:none}.dropdown li a,.dropdown li span{color:#aaa;display:block;padding:10px 20px;z-index:102}#heading:after,#heading:before,#hohContainer:after,#hohContainer:before,#socialButtons #socialIcons:after,#socialButtons #socialIcons:before{display:table;content:" "}.dropdown:after,.dropdown:before{left:0;right:0}.dropdown.active{opacity:1;max-height:25pc;overflow-y:scroll}.dropdown.active .viewport_container{height:100%;overflow:hidden;position:relative;width:100%}#bg,#bg:after,#socialButtons{position:absolute}.dropdown.active .viewport_container .viewport{bottom:0;left:0;overflow-x:'auto';overflow-y:'auto';position:absolute;right:-18px;top:0}body{background:#f9f9f9;overflow-x:hidden}#bg{background:#333;top:0;left:0;z-index:-1}#bg:after{border-left:125pc solid transparent;border-right:0 solid transparent;border-bottom:200px solid #F9F9F9;clear:both;height:0;left:0;bottom:0;width:0}#heading .row,#hohContainer .row{width:auto}#hohContainer{display:block;margin:0 auto;padding:0}#hohContainer .row.collapse{margin:0}#heading{display:block;margin:0 auto;padding:0}#heading .row.collapse{margin:0}#heading #main_header{margin:0 auto}#heading #logo_container,#heading #powered_by{float:left;min-height:1px;position:relative;width:50%}#heading #logo_container p{text-align:left}#heading #logo_container p a{border-bottom:none}#heading #powered_by ul{text-align:right}#heading #powered_by ul #reactjs a{color:#00d8ff;font-family:"Helvetica Neue",Helvetica,Roboto,Arial,sans-serif}#heading #powered_by ul #reactjs a img{height:25px;position:relative;top:7px;width:25px}#heading #powered_by ul #wikipedia a{color:#fff;font-family:'Crimson+Text';letter-spacing:.1em;text-transform:uppercase}#heading #powered_by ul #wikipedia a small{font-size:.8em}#heading h1{color:#fff;margin-top:75pt;text-align:center}#heading h1 #top_title{font-size:2pc;font-family:'Open Sans';font-weight:300;letter-spacing:.25em;text-transform:uppercase}#heading h1 #lower_title{font-size:28px;position:relative;top:-1em}#heading p{color:#fff;margin-bottom:1em;text-align:center}#heading p a{border-bottom:1px dotted #fff;color:#fff}#socialButtons{-webkit-transition:all .5s;-moz-transition:all .5s;-o-transition:all .5s;transition:all .5s;color:#00b5ff;right:.5em}#socialButtons.active,#socialButtons:hover{color:#535f5f}#socialButtons .socialBox{height:36px;position:relative;width:41px}#socialButtons #socialIcons{display:block;margin:0 auto;padding:0;bottom:37px;position:absolute;right:5px}#socialButtons #socialIcons .row{width:auto}#socialButtons #socialIcons .row.collapse{margin:0}#socialButtons #circleBg{-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;background-clip:padding-box;background-color:#fff;display:block;position:relative;right:.9em}#socialButtons #circleBg .fa-share-alt-square{left:-1px;top:-4px}#socialButtons .fa{cursor:pointer;position:relative}#socialButtons .fa-share-alt-square{font-size:2em}#socialButtons .count,#socialButtons .share{text-align:center;text-decoration:none}#socialButtons .count{color:#fff;font-size:14px;left:-50px;position:absolute;text-align:right;top:6px;width:42px}#socialButtons .share{-webkit-border-radius:50%;-moz-border-radius:50%;border-radius:50%;background-clip:padding-box;color:#fff;display:inline-block;height:30px;line-height:28px;position:absolute;width:31px}#socialButtons .share:hover{color:#fff;text-decoration:none}#socialButtons .fa img{position:relative;top:2px;width:1pc}#socialButtons .bufferapp,#socialButtons .facebook,#socialButtons .pinterest,#socialButtons .stumbleupon,#socialButtons .twitter{height:100%;text-align:center;width:100%;-webkit-border-radius:4px;-webkit-background-clip:padding-box;-moz-border-radius:4px;-moz-background-clip:padding;border-radius:4px;background-clip:padding-box}#socialButtons #twitter .share{text-shadow:1px 0 0 #0077be;background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMyNmMzZWIiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwODBkNiIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=);background-image:-webkit-linear-gradient(top,#26c3eb 0,#0080d6 100%);background-image:-moz-linear-gradient(top,#26c3eb 0,#0080d6 100%);background-image:-o-linear-gradient(top,#26c3eb 0,#0080d6 100%);background-image:linear-gradient(to bottom,#26c3eb 0,#0080d6 100%)}#socialButtons #facebook .share{background:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMzYjU5OTgiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzEzMzc4MyIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=) #3b5998;text-shadow:1px 0 0 #26427e;background-image:-webkit-linear-gradient(top,#3b5998 0,#133783 100%);background-image:-moz-linear-gradient(top,#3b5998 0,#133783 100%);background-image:-o-linear-gradient(top,#3b5998 0,#133783 100%);background-image:linear-gradient(to bottom,#3b5998 0,#133783 100%)}#socialButtons #googleplus .share{background:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiM2ZDZkNmQiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzQzNDM0MyIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=) #6d6d6d;text-shadow:1px 0 0 #222;background-image:-webkit-linear-gradient(top,#6d6d6d 0,#434343 100%);background-image:-moz-linear-gradient(top,#6d6d6d 0,#434343 100%);background-image:-o-linear-gradient(top,#6d6d6d 0,#434343 100%);background-image:linear-gradient(to bottom,#6d6d6d 0,#434343 100%)}#socialButtons #linkedin .share{background:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiM3NGJiZGIiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwN2ZiMiIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=) #6d6d6d;text-shadow:1px 0 0 #26427e;background-image:-webkit-linear-gradient(top,#74bbdb 0,#007fb2 100%);background-image:-moz-linear-gradient(top,#74bbdb 0,#007fb2 100%);background-image:-o-linear-gradient(top,#74bbdb 0,#007fb2 100%);background-image:linear-gradient(to bottom,#74bbdb 0,#007fb2 100%)}#socialButtons #stumbleupon .share{background:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMSAxIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIj48bGluZWFyR3JhZGllbnQgaWQ9Imxlc3NoYXQtZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNlYjQ5MjQiIHN0b3Atb3BhY2l0eT0iMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2IxMjQwMyIgc3RvcC1vcGFjaXR5PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2xlc3NoYXQtZ2VuZXJhdGVkKSIgLz48L3N2Zz4=) #eb4924;text-shadow:1px 0 0 #26427e;background-image:-webkit-linear-gradient(top,#eb4924 0,#b12403 100%);background-image:-moz-linear-gradient(top,#eb4924 0,#b12403 100%);background-image:-o-linear-gradient(top,#eb4924 0,#b12403 100%);background-image:linear-gradient(to bottom,#eb4924 0,#b12403 100%)}#controls .yearPanel,#controls p{-webkit-background-clip:padding-box;-moz-background-clip:padding}.socialTransition-appear{-webkit-transition:all 2s;-moz-transition:all 2s;-o-transition:all 2s;transition:all 2s;max-height:1px;opacity:.01}.socialTransition-appear.socialTransition-appear-active{max-height:500px;opacity:1}#controls,#itemDetail,#items,#mapAndControls{display:block;margin:0 auto;padding:0;width:75pc}#controls:after,#controls:before,#itemDetail:after,#itemDetail:before,#items:after,#items:before,#mapAndControls:after,#mapAndControls:before{content:" ";display:table}#controls .row,#itemDetail .row,#items .row,#mapAndControls .row{width:auto}#controls .row.collapse,#itemDetail .row.collapse,#items .row.collapse,#mapAndControls .row.collapse{margin:0}#mapAndControls{position:relative}#gmap{-webkit-box-shadow:0 10px 55px 0 rgba(0,0,0,.3);-moz-box-shadow:0 10px 55px 0 rgba(0,0,0,.3);box-shadow:0 10px 55px 0 rgba(0,0,0,.3)}#mapCanvas{display:block}#controls{background:rgba(0,0,0,.5);bottom:0;padding:11px 11px 18px;position:absolute}#controls p{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background:#fff;cursor:pointer;padding:.2em .5em;text-transform:capitalize}#controls label{color:#fff;margin-bottom:.2em}#controls .panel{float:left;min-height:1px;position:relative;width:33.33333%;padding-left:13px;padding-right:13px}#controls .yearPanel{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background-clip:padding-box;background-color:#FFF;display:inline-block;font-size:15px;padding:3px 9px}#hideItemDetail,.fa_button{-webkit-border-radius:50%;-webkit-background-clip:padding-box;-moz-border-radius:50%;-moz-background-clip:padding;cursor:pointer}#controls #endDate,#controls #startDate{cursor:pointer;display:inline-block;margin:0 1em 0 22px;width:280px}.fa_button{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;border-radius:50%;background-clip:padding-box;-webkit-box-shadow:1px 1px 1px #ccc;-moz-box-shadow:1px 1px 1px #ccc;box-shadow:1px 1px 1px #ccc;-webkit-transition:background-color .5s;-moz-transition:background-color .5s;-o-transition:background-color .5s;transition:background-color .5s;background-color:#00b5ff;border:none;color:#fff;display:block;height:30px;outline:0;text-align:center;text-decoration:none;width:30px;zoom:1}.fa_button#backButton,.fa_button#forwardButton,.fa_button#galleryBack,.fa_button#galleryForward{cursor:pointer;font-size:18px;position:absolute}.fa_button#backButton .fa,.fa_button#forwardButton .fa,.fa_button#galleryBack .fa,.fa_button#galleryForward .fa{position:relative;top:1px}.fa_button#backButton,.fa_button#forwardButton{bottom:35px}.fa_button#backButton{left:-50px}.fa_button#forwardButton{right:-50px}.fa_button#backButton .fa,.fa_button#galleryBack .fa{left:-1px}.fa_button#forwardButton .fa,.fa_button#galleryForward .fa{left:1px}.fa_button:hover{background-color:#535f5f;color:#fff}#items ul{list-style-type:none;margin-left:0}#items ul .yearTitle{border-bottom:1px solid #e8e8e8;color:#727272;margin:60px 0 30px;padding-bottom:30px}#items ul .itemPanel{-webkit-box-shadow:0 2px 4px rgba(0,0,0,.24);-moz-box-shadow:0 2px 4px rgba(0,0,0,.24);box-shadow:0 2px 4px rgba(0,0,0,.24);background:#fff;cursor:pointer;margin-bottom:30px}#items ul .itemPanel.highlightMap{background-color:#d5edf5}#items ul .itemPanel.highlightClick{background-color:#f5f4d5}#items ul .itemPanel p{margin-bottom:0;padding:1em}#items ul .itemPanel p a{color:#727272}#items ul .itemPanel .readmore{border-top:1px solid #eee;color:#00b5ff;display:block;font-size:.8em;padding:1em;text-align:right;width:100%}.itemDetailTransition-appear{opacity:.01;-webkit-transition:opacity .5s ease-in;-moz-transition:opacity .5s ease-in;-o-transition:opacity .5s ease-in;transition:opacity .5s ease-in}.itemDetailTransition-appear.itemDetailTransition-appear-active{opacity:1}#itemDetail{-webkit-box-shadow:0 4px 10px rgba(0,0,0,.23);-moz-box-shadow:0 4px 10px rgba(0,0,0,.23);box-shadow:0 4px 10px rgba(0,0,0,.23);background:#fff;overflow-y:auto;padding:1em;position:fixed;right:15px;top:10px}#itemDetail h3,#itemDetail h4{border-bottom:1px solid #e8e8e8;font-family:'Crimson+Text';line-height:1.5;padding-bottom:1em}#itemDetail h3{font-size:24px;margin:.5em 0 1.5em}#itemDetail h4{font-size:20px;margin:2em 0 1em}#itemDetail ul,.paginator{list-style-type:none;margin-left:0}#itemDetail p,#itemDetail ul li{font-size:15px}#itemDetail p#mainLink{font-weight:700}#itemDetail p#mainLink a{font-weight:400}#itemDetail #galleryTitle{position:relative}#itemDetail #galleryTitle #galleryBack,#itemDetail #galleryTitle #galleryForward{top:3px}#itemDetail #galleryTitle #galleryBack{left:89px}#itemDetail #galleryTitle #galleryForward{left:130px}#itemDetail #gallery img{float:left;min-height:1px;position:relative;width:33.33333%;padding-left:13px;padding-right:13px}.paginator li,.paginator li.selected,.paginator li:hover{padding:2px 10px}#hideItemDetail{border-radius:50%;-webkit-box-shadow:1px 1px 1px #ccc;-moz-box-shadow:1px 1px 1px #ccc;box-shadow:1px 1px 1px #ccc;-webkit-transition:right .8s;-moz-transition:right .8s;-o-transition:right .8s;transition:right .8s;background:#00b5ff;color:#fff;height:35px;line-height:2;position:fixed;right:-100%;text-align:center;top:4px;width:35px;z-index:200}.paginator{overflow:hidden;text-align:center}.paginator:after,.paginator:before{display:table}.paginator li:before{margin:0 .66667em;position:relative;top:1px}#footer p,.paginator li form,.paginator li input{margin-bottom:0}.paginator li:first-child:before{margin:0}.paginator li{display:inline-block;cursor:pointer;margin:0}.paginator li a{color:#ccc}.paginator li.selected a{color:#00b5ff}.paginator li.no_more{-webkit-border-radius:2px;-webkit-background-clip:padding-box;-moz-border-radius:2px;-moz-background-clip:padding;border-radius:2px;background-clip:padding-box;background-color:#535f5f;padding:2px 10px}.paginator li.no_more a{color:#fff}.paginator li:hover a{color:#535f5f}#footer{background:#222;color:#ccc}#footer p{border-top:1px solid #fff;color:#fff;padding:2em;text-align:center}#footer a{border-bottom:1px dotted #ccc;color:#ccc}@media screen and (max-width:639px){#controls,#itemDetail,#items,#mapAndControls,#mapCanvas{width:285px}a.button,button,html input[type=button],input[type=submit],input[type=reset]{line-height:1.278}#heading,#hohContainer{width:300px}#heading{margin:40px auto 150px}#main_header{margin:0 auto;width:280px}#circleBg{height:30px;width:30px}#circleBg .fa-share-alt-square{font-size:2.7em}#mapCanvas{height:250px}#controls .panel{padding:0}#controls #endDate,#controls #startDate{width:72px}#hideItemDetail{height:28px;right:283px;width:28px}}@media screen and (max-width:799px){body{font-size:.875em}#heading h1{margin-bottom:1em;margin-top:70px}#heading h1 #lower_title{line-height:0;top:0}}@media screen and (min-width:800px){h1:first-child,h2:first-child,h3:first-child{margin-top:0}}@media screen and (min-width:640px) and (max-width:799px){#controls,#itemDetail,#items,#mapAndControls,#mapCanvas{width:425px}#heading,#hohContainer{width:540px}#heading{margin:40px auto 5pc}#main_header{margin:0 auto;width:5in}#circleBg{height:30px;width:30px}#circleBg .fa-share-alt-square{font-size:2.7em}#mapCanvas{height:325px}#controls #endDate,#controls #startDate{width:75pt}#hideItemDetail{right:423px}}@media screen and (min-width:1376px){body{font-size:1.125em}}@media screen and (min-width:800px) and (max-width:1023px){#controls,#itemDetail,#items,#mapAndControls,#mapCanvas{width:625px}#heading,#hohContainer{width:740px}#heading{margin:40px auto 5pc}#main_header{margin:0 auto;width:680px}#circleBg{height:30px;width:30px}#circleBg .fa-share-alt-square{font-size:2.3em}#mapCanvas{height:455px}#controls #endDate,#controls #startDate{width:130px}#hideItemDetail{height:28px;line-height:1.6;right:623px;width:28px}}@media screen and (min-width:1024px) and (max-width:1375px){#controls,#itemDetail,#items,#mapAndControls,#mapCanvas{width:900px}#heading,#hohContainer{width:980px}#heading{margin:75px auto}#circleBg{height:30px;width:30px}#circleBg .fa-share-alt-square{font-size:2.3em}#mapCanvas{height:600px}#controls #endDate,#controls #startDate{width:200px}#hideItemDetail{right:897px}}@media screen and (min-width:1376px) and (max-width:1839px){#controls,#itemDetail,#items,#mapAndControls,#mapCanvas{width:75pc}#heading,#hohContainer{width:80pc}#heading{margin:75pt auto}#circleBg{height:30px;width:30px}#mapCanvas{height:600px}#controls #endDate,#controls #startDate{width:280px}#hideItemDetail{height:28px;line-height:1.6;right:1197px;width:28px}}@media screen and (min-width:1840px){#controls,#itemDetail,#items,#mapAndControls,#mapCanvas{width:975pt}body{font-size:1.125em}#heading,#hohContainer{width:15in}#heading{margin:75pt auto}#circleBg{height:30px;width:30px}#mapCanvas{height:600px}#controls #endDate,#controls #startDate{width:20pc}#hideItemDetail{right:1297px}}
--------------------------------------------------------------------------------
/public/functions.js:
--------------------------------------------------------------------------------
1 | /*
2 | ---
3 | name: Selectors
4 | description: Deals with selecting of things
5 | details: inspired by //product.voxmedia.com/til/2015/2/16/8047537/easy-selector-engine-with-vanilla-javascript
6 | provides: $, $$
7 | ...
8 | */
9 |
10 | var $ = document.getElementById.bind(document);
11 | var $$ = document.querySelectorAll.bind(document);
12 |
13 | /*
14 | ---
15 | name: IsSet
16 | description: a tidy function so you don't have to check undefined all the bloody time
17 | provides: isset
18 | ...
19 | */
20 |
21 | function isset (obj) { return typeof obj !== 'undefined'; }
22 |
23 | /*
24 | ---
25 | name: mobileCheck
26 | description: Checks if we're on a mobile device
27 | details: inspired by //stackoverflow.com/a/11381730/989439
28 | provides: mobileCheck
29 | ...
30 | */
31 |
32 | function mobileCheck () {
33 | var check = false;
34 | (function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
35 | return check;
36 | }
37 |
38 | /*
39 | ---
40 | name: getViewportSize
41 | description: Gets the dimensions of the viewport
42 | ...
43 | */
44 |
45 | function getViewportSize() {
46 | var dims = {};
47 | dims.width = 0;
48 | dims.height = 0;
49 |
50 | if( typeof( window.innerWidth ) == 'number' ) {
51 | //Non-IE
52 | dims.width = window.innerWidth;
53 | dims.height = window.innerHeight;
54 | }
55 | else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
56 | //IE 6+ in 'standards compliant mode'
57 | dims.width = document.documentElement.clientWidth;
58 | dims.height = document.documentElement.clientHeight;
59 | }
60 | else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
61 | //IE 4 compatible
62 | dims.width = document.body.clientWidth;
63 | dims.height = document.body.clientHeight;
64 | }
65 |
66 | return dims;
67 | }
68 |
69 | /*
70 | ---
71 | name: escapeRegExp
72 | description: escapes regex
73 | ...
74 | */
75 |
76 | function escapeRegExp (string) {
77 | return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
78 | }
79 |
80 |
81 | /*
82 | ---
83 | Clouds
84 | ---
85 | */
86 |
87 | var camera, scene, renderer,
88 | geometry, material, mesh;
89 |
90 | function init () {
91 | clock = new THREE.Clock();
92 |
93 | renderer = new THREE.WebGLRenderer();
94 |
95 | scene = new THREE.Scene();
96 |
97 | camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
98 | camera.position.z = 1000;
99 | scene.add( camera );
100 |
101 | geometry = new THREE.BoxGeometry( 200, 200, 200 );
102 | material = new THREE.MeshLambertMaterial( { color: 0x93887d, wireframe: false } );
103 | mesh = new THREE.Mesh( geometry, material );
104 | //scene.add( mesh );
105 | cubeSineDriver = 0;
106 |
107 | light = new THREE.DirectionalLight(0xfffadd, 1.5);
108 | light.position.set(-1,0,1);
109 | scene.add(light);
110 |
111 | smokeTexture = THREE.ImageUtils.loadTexture('/history-of-humanity/imgs/Smoke-Element.png');
112 | smokeMaterial = new THREE.MeshLambertMaterial({
113 | color: 0x93887d,
114 | map: smokeTexture,
115 | transparent: true
116 | });
117 | smokeMaterial.map.minFilter = THREE.LinearFilter;
118 |
119 | smokeGeo = new THREE.PlaneBufferGeometry(300,300);
120 | smokeParticles = [];
121 |
122 | for (p = 0; p < 200; p++) {
123 | var particle = new THREE.Mesh(smokeGeo,smokeMaterial);
124 | particle.position.set(Math.random() * 500 - 250, Math.random() * 500 - 250, Math.random() * 1000 - 30);
125 | particle.rotation.z = Math.random() * 360;
126 | scene.add(particle);
127 | smokeParticles.push(particle);
128 | }
129 |
130 | $('bg').appendChild(renderer.domElement);
131 |
132 | window.addEventListener('resize', onWindowResize, false);
133 | }
134 |
135 | function animate () {
136 | // note: three.js includes requestAnimationFrame shim
137 | delta = clock.getDelta();
138 | requestAnimationFrame( animate );
139 | evolveSmoke();
140 | render();
141 | onWindowResize();
142 | }
143 |
144 | function evolveSmoke () {
145 | var sp = smokeParticles.length;
146 | while(sp--) {
147 | smokeParticles[sp].rotation.z += (delta * 0.1);
148 | }
149 | }
150 |
151 | function updateLightPosition () {
152 | var time = Date.now() * 0.0002;
153 |
154 | light.position.x = Math.sin(time * 5);
155 | light.position.y = Math.cos(1/time);
156 | }
157 |
158 | function render () {
159 | mesh.rotation.x += 0.005;
160 | mesh.rotation.y += 0.01;
161 | cubeSineDriver += .01;
162 | mesh.position.z = 100 + (Math.sin(cubeSineDriver) * 500);
163 | updateLightPosition();
164 | renderer.render( scene, camera );
165 | }
166 |
167 | function onWindowResize () {
168 | var dims = getViewportSize();
169 |
170 | var cWidth = dims.width;
171 | var cHeight = 670;
172 |
173 | if (!mobileCheck())
174 | cWidth = cWidth - 17;
175 |
176 | if (cHeight < dims.height)
177 | cHeight = dims.height;
178 | else if (cHeight > 1200)
179 | cHeight = 1200;
180 |
181 | camera.aspect = dims.width / dims.height;
182 | camera.updateProjectionMatrix();
183 |
184 | renderer.setSize(cWidth, cHeight);
185 | }
--------------------------------------------------------------------------------
/public/imgs/Smoke-Element.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwatsonwailes/history-of-humanity/d8867d65a248c4711059dba62b56fab14cf79a13/public/imgs/Smoke-Element.png
--------------------------------------------------------------------------------
/public/imgs/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwatsonwailes/history-of-humanity/d8867d65a248c4711059dba62b56fab14cf79a13/public/imgs/logo.png
--------------------------------------------------------------------------------
/public/imgs/react-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
--------------------------------------------------------------------------------
/public/markerwithlabel.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @name MarkerWithLabel for V3
3 | * @version 1.1.10 [April 8, 2014]
4 | * @author Gary Little (inspired by code from Marc Ridey of Google).
5 | * @copyright Copyright 2012 Gary Little [gary at luxcentral.com]
6 | * @fileoverview MarkerWithLabel extends the Google Maps JavaScript API V3
7 | * google.maps.Marker
class.
8 | *
9 | * MarkerWithLabel allows you to define markers with associated labels. As you would expect, 10 | * if the marker is draggable, so too will be the label. In addition, a marker with a label 11 | * responds to all mouse events in the same manner as a regular marker. It also fires mouse 12 | * events and "property changed" events just as a regular marker would. Version 1.1 adds 13 | * support for the raiseOnDrag feature introduced in API V3.3. 14 | *
15 | * If you drag a marker by its label, you can cancel the drag and return the marker to its
16 | * original position by pressing the Esc
key. This doesn't work if you drag the marker
17 | * itself because this feature is not (yet) supported in the google.maps.Marker
class.
18 | */
19 |
20 | /*!
21 | *
22 | * Licensed under the Apache License, Version 2.0 (the "License");
23 | * you may not use this file except in compliance with the License.
24 | * You may obtain a copy of the License at
25 | *
26 | * http://www.apache.org/licenses/LICENSE-2.0
27 | *
28 | * Unless required by applicable law or agreed to in writing, software
29 | * distributed under the License is distributed on an "AS IS" BASIS,
30 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 | * See the License for the specific language governing permissions and
32 | * limitations under the License.
33 | */
34 |
35 | /*jslint browser:true */
36 | /*global document,google */
37 |
38 | /**
39 | * @param {Function} childCtor Child class.
40 | * @param {Function} parentCtor Parent class.
41 | * @private
42 | */
43 | function inherits(childCtor, parentCtor) {
44 | /* @constructor */
45 | function tempCtor() {}
46 | tempCtor.prototype = parentCtor.prototype;
47 | childCtor.superClass_ = parentCtor.prototype;
48 | childCtor.prototype = new tempCtor();
49 | /* @override */
50 | childCtor.prototype.constructor = childCtor;
51 | }
52 |
53 | /**
54 | * This constructor creates a label and associates it with a marker.
55 | * It is for the private use of the MarkerWithLabel class.
56 | * @constructor
57 | * @param {Marker} marker The marker with which the label is to be associated.
58 | * @param {string} crossURL The URL of the cross image =.
59 | * @param {string} handCursor The URL of the hand cursor.
60 | * @private
61 | */
62 | function MarkerLabel_(marker, crossURL, handCursorURL) {
63 | this.marker_ = marker;
64 | this.handCursorURL_ = marker.handCursorURL;
65 |
66 | this.labelDiv_ = document.createElement("div");
67 | this.labelDiv_.style.cssText = "position: absolute; overflow: hidden;";
68 |
69 | // Set up the DIV for handling mouse events in the label. This DIV forms a transparent veil
70 | // in the "overlayMouseTarget" pane, a veil that covers just the label. This is done so that
71 | // events can be captured even if the label is in the shadow of a google.maps.InfoWindow.
72 | // Code is included here to ensure the veil is always exactly the same size as the label.
73 | this.eventDiv_ = document.createElement("div");
74 | this.eventDiv_.style.cssText = this.labelDiv_.style.cssText;
75 |
76 | // This is needed for proper behavior on MSIE:
77 | this.eventDiv_.setAttribute("onselectstart", "return false;");
78 | this.eventDiv_.setAttribute("ondragstart", "return false;");
79 |
80 | // Get the DIV for the "X" to be displayed when the marker is raised.
81 | this.crossDiv_ = MarkerLabel_.getSharedCross(crossURL);
82 | }
83 |
84 | inherits(MarkerLabel_, google.maps.OverlayView);
85 |
86 | /**
87 | * Returns the DIV for the cross used when dragging a marker when the
88 | * raiseOnDrag parameter set to true. One cross is shared with all markers.
89 | * @param {string} crossURL The URL of the cross image =.
90 | * @private
91 | */
92 | MarkerLabel_.getSharedCross = function (crossURL) {
93 | var div;
94 | if (typeof MarkerLabel_.getSharedCross.crossDiv === "undefined") {
95 | div = document.createElement("img");
96 | div.style.cssText = "position: absolute; z-index: 1000002; display: none;";
97 | // Hopefully Google never changes the standard "X" attributes:
98 | div.style.marginLeft = "-8px";
99 | div.style.marginTop = "-9px";
100 | div.src = crossURL;
101 | MarkerLabel_.getSharedCross.crossDiv = div;
102 | }
103 | return MarkerLabel_.getSharedCross.crossDiv;
104 | };
105 |
106 | /**
107 | * Adds the DIV representing the label to the DOM. This method is called
108 | * automatically when the marker's setMap
method is called.
109 | * @private
110 | */
111 | MarkerLabel_.prototype.onAdd = function () {
112 | var me = this;
113 | var cMouseIsDown = false;
114 | var cDraggingLabel = false;
115 | var cSavedZIndex;
116 | var cLatOffset, cLngOffset;
117 | var cIgnoreClick;
118 | var cRaiseEnabled;
119 | var cStartPosition;
120 | var cStartCenter;
121 | // Constants:
122 | var cRaiseOffset = 20;
123 | var cDraggingCursor = "url(" + this.handCursorURL_ + ")";
124 |
125 | // Stops all processing of an event.
126 | //
127 | var cAbortEvent = function (e) {
128 | if (e.preventDefault) {
129 | e.preventDefault();
130 | }
131 | e.cancelBubble = true;
132 | if (e.stopPropagation) {
133 | e.stopPropagation();
134 | }
135 | };
136 |
137 | var cStopBounce = function () {
138 | me.marker_.setAnimation(null);
139 | };
140 |
141 | this.getPanes().overlayImage.appendChild(this.labelDiv_);
142 | this.getPanes().overlayMouseTarget.appendChild(this.eventDiv_);
143 | // One cross is shared with all markers, so only add it once:
144 | if (typeof MarkerLabel_.getSharedCross.processed === "undefined") {
145 | this.getPanes().overlayImage.appendChild(this.crossDiv_);
146 | MarkerLabel_.getSharedCross.processed = true;
147 | }
148 |
149 | this.listeners_ = [
150 | google.maps.event.addDomListener(this.eventDiv_, "mouseover", function (e) {
151 | if (me.marker_.getDraggable() || me.marker_.getClickable()) {
152 | this.style.cursor = "pointer";
153 | google.maps.event.trigger(me.marker_, "mouseover", e);
154 | }
155 | }),
156 | google.maps.event.addDomListener(this.eventDiv_, "mouseout", function (e) {
157 | if ((me.marker_.getDraggable() || me.marker_.getClickable()) && !cDraggingLabel) {
158 | this.style.cursor = me.marker_.getCursor();
159 | google.maps.event.trigger(me.marker_, "mouseout", e);
160 | }
161 | }),
162 | google.maps.event.addDomListener(this.eventDiv_, "mousedown", function (e) {
163 | cDraggingLabel = false;
164 | if (me.marker_.getDraggable()) {
165 | cMouseIsDown = true;
166 | this.style.cursor = cDraggingCursor;
167 | }
168 | if (me.marker_.getDraggable() || me.marker_.getClickable()) {
169 | google.maps.event.trigger(me.marker_, "mousedown", e);
170 | cAbortEvent(e); // Prevent map pan when starting a drag on a label
171 | }
172 | }),
173 | google.maps.event.addDomListener(document, "mouseup", function (mEvent) {
174 | var position;
175 | if (cMouseIsDown) {
176 | cMouseIsDown = false;
177 | me.eventDiv_.style.cursor = "pointer";
178 | google.maps.event.trigger(me.marker_, "mouseup", mEvent);
179 | }
180 | if (cDraggingLabel) {
181 | if (cRaiseEnabled) { // Lower the marker & label
182 | position = me.getProjection().fromLatLngToDivPixel(me.marker_.getPosition());
183 | position.y += cRaiseOffset;
184 | me.marker_.setPosition(me.getProjection().fromDivPixelToLatLng(position));
185 | // This is not the same bouncing style as when the marker portion is dragged,
186 | // but it will have to do:
187 | try { // Will fail if running Google Maps API earlier than V3.3
188 | me.marker_.setAnimation(google.maps.Animation.BOUNCE);
189 | setTimeout(cStopBounce, 1406);
190 | } catch (e) {}
191 | }
192 | me.crossDiv_.style.display = "none";
193 | me.marker_.setZIndex(cSavedZIndex);
194 | cIgnoreClick = true; // Set flag to ignore the click event reported after a label drag
195 | cDraggingLabel = false;
196 | mEvent.latLng = me.marker_.getPosition();
197 | google.maps.event.trigger(me.marker_, "dragend", mEvent);
198 | }
199 | }),
200 | google.maps.event.addListener(me.marker_.getMap(), "mousemove", function (mEvent) {
201 | var position;
202 | if (cMouseIsDown) {
203 | if (cDraggingLabel) {
204 | // Change the reported location from the mouse position to the marker position:
205 | mEvent.latLng = new google.maps.LatLng(mEvent.latLng.lat() - cLatOffset, mEvent.latLng.lng() - cLngOffset);
206 | position = me.getProjection().fromLatLngToDivPixel(mEvent.latLng);
207 | if (cRaiseEnabled) {
208 | me.crossDiv_.style.left = position.x + "px";
209 | me.crossDiv_.style.top = position.y + "px";
210 | me.crossDiv_.style.display = "";
211 | position.y -= cRaiseOffset;
212 | }
213 | me.marker_.setPosition(me.getProjection().fromDivPixelToLatLng(position));
214 | if (cRaiseEnabled) { // Don't raise the veil; this hack needed to make MSIE act properly
215 | me.eventDiv_.style.top = (position.y + cRaiseOffset) + "px";
216 | }
217 | google.maps.event.trigger(me.marker_, "drag", mEvent);
218 | } else {
219 | // Calculate offsets from the click point to the marker position:
220 | cLatOffset = mEvent.latLng.lat() - me.marker_.getPosition().lat();
221 | cLngOffset = mEvent.latLng.lng() - me.marker_.getPosition().lng();
222 | cSavedZIndex = me.marker_.getZIndex();
223 | cStartPosition = me.marker_.getPosition();
224 | cStartCenter = me.marker_.getMap().getCenter();
225 | cRaiseEnabled = me.marker_.get("raiseOnDrag");
226 | cDraggingLabel = true;
227 | me.marker_.setZIndex(1000000); // Moves the marker & label to the foreground during a drag
228 | mEvent.latLng = me.marker_.getPosition();
229 | google.maps.event.trigger(me.marker_, "dragstart", mEvent);
230 | }
231 | }
232 | }),
233 | google.maps.event.addDomListener(document, "keydown", function (e) {
234 | if (cDraggingLabel) {
235 | if (e.keyCode === 27) { // Esc key
236 | cRaiseEnabled = false;
237 | me.marker_.setPosition(cStartPosition);
238 | me.marker_.getMap().setCenter(cStartCenter);
239 | google.maps.event.trigger(document, "mouseup", e);
240 | }
241 | }
242 | }),
243 | google.maps.event.addDomListener(this.eventDiv_, "click", function (e) {
244 | if (me.marker_.getDraggable() || me.marker_.getClickable()) {
245 | if (cIgnoreClick) { // Ignore the click reported when a label drag ends
246 | cIgnoreClick = false;
247 | } else {
248 | google.maps.event.trigger(me.marker_, "click", e);
249 | cAbortEvent(e); // Prevent click from being passed on to map
250 | }
251 | }
252 | }),
253 | google.maps.event.addDomListener(this.eventDiv_, "dblclick", function (e) {
254 | if (me.marker_.getDraggable() || me.marker_.getClickable()) {
255 | google.maps.event.trigger(me.marker_, "dblclick", e);
256 | cAbortEvent(e); // Prevent map zoom when double-clicking on a label
257 | }
258 | }),
259 | google.maps.event.addListener(this.marker_, "dragstart", function (mEvent) {
260 | if (!cDraggingLabel) {
261 | cRaiseEnabled = this.get("raiseOnDrag");
262 | }
263 | }),
264 | google.maps.event.addListener(this.marker_, "drag", function (mEvent) {
265 | if (!cDraggingLabel) {
266 | if (cRaiseEnabled) {
267 | me.setPosition(cRaiseOffset);
268 | // During a drag, the marker's z-index is temporarily set to 1000000 to
269 | // ensure it appears above all other markers. Also set the label's z-index
270 | // to 1000000 (plus or minus 1 depending on whether the label is supposed
271 | // to be above or below the marker).
272 | me.labelDiv_.style.zIndex = 1000000 + (this.get("labelInBackground") ? -1 : +1);
273 | }
274 | }
275 | }),
276 | google.maps.event.addListener(this.marker_, "dragend", function (mEvent) {
277 | if (!cDraggingLabel) {
278 | if (cRaiseEnabled) {
279 | me.setPosition(0); // Also restores z-index of label
280 | }
281 | }
282 | }),
283 | google.maps.event.addListener(this.marker_, "position_changed", function () {
284 | me.setPosition();
285 | }),
286 | google.maps.event.addListener(this.marker_, "zindex_changed", function () {
287 | me.setZIndex();
288 | }),
289 | google.maps.event.addListener(this.marker_, "visible_changed", function () {
290 | me.setVisible();
291 | }),
292 | google.maps.event.addListener(this.marker_, "labelvisible_changed", function () {
293 | me.setVisible();
294 | }),
295 | google.maps.event.addListener(this.marker_, "title_changed", function () {
296 | me.setTitle();
297 | }),
298 | google.maps.event.addListener(this.marker_, "labelcontent_changed", function () {
299 | me.setContent();
300 | }),
301 | google.maps.event.addListener(this.marker_, "labelanchor_changed", function () {
302 | me.setAnchor();
303 | }),
304 | google.maps.event.addListener(this.marker_, "labelclass_changed", function () {
305 | me.setStyles();
306 | }),
307 | google.maps.event.addListener(this.marker_, "labelstyle_changed", function () {
308 | me.setStyles();
309 | })
310 | ];
311 | };
312 |
313 | /**
314 | * Removes the DIV for the label from the DOM. It also removes all event handlers.
315 | * This method is called automatically when the marker's setMap(null)
316 | * method is called.
317 | * @private
318 | */
319 | MarkerLabel_.prototype.onRemove = function () {
320 | var i;
321 | this.labelDiv_.parentNode.removeChild(this.labelDiv_);
322 | this.eventDiv_.parentNode.removeChild(this.eventDiv_);
323 |
324 | // Remove event listeners:
325 | for (i = 0; i < this.listeners_.length; i++) {
326 | google.maps.event.removeListener(this.listeners_[i]);
327 | }
328 | };
329 |
330 | /**
331 | * Draws the label on the map.
332 | * @private
333 | */
334 | MarkerLabel_.prototype.draw = function () {
335 | this.setContent();
336 | this.setTitle();
337 | this.setStyles();
338 | };
339 |
340 | /**
341 | * Sets the content of the label.
342 | * The content can be plain text or an HTML DOM node.
343 | * @private
344 | */
345 | MarkerLabel_.prototype.setContent = function () {
346 | var content = this.marker_.get("labelContent");
347 | if (typeof content.nodeType === "undefined") {
348 | this.labelDiv_.innerHTML = content;
349 | this.eventDiv_.innerHTML = this.labelDiv_.innerHTML;
350 | } else {
351 | this.labelDiv_.innerHTML = ""; // Remove current content
352 | this.labelDiv_.appendChild(content);
353 | content = content.cloneNode(true);
354 | this.eventDiv_.innerHTML = ""; // Remove current content
355 | this.eventDiv_.appendChild(content);
356 | }
357 | };
358 |
359 | /**
360 | * Sets the content of the tool tip for the label. It is
361 | * always set to be the same as for the marker itself.
362 | * @private
363 | */
364 | MarkerLabel_.prototype.setTitle = function () {
365 | this.eventDiv_.title = this.marker_.getTitle() || "";
366 | };
367 |
368 | /**
369 | * Sets the style of the label by setting the style sheet and applying
370 | * other specific styles requested.
371 | * @private
372 | */
373 | MarkerLabel_.prototype.setStyles = function () {
374 | var i, labelStyle;
375 |
376 | // Apply style values from the style sheet defined in the labelClass parameter:
377 | this.labelDiv_.className = this.marker_.get("labelClass");
378 | this.eventDiv_.className = this.labelDiv_.className;
379 |
380 | // Clear existing inline style values:
381 | this.labelDiv_.style.cssText = "";
382 | this.eventDiv_.style.cssText = "";
383 | // Apply style values defined in the labelStyle parameter:
384 | labelStyle = this.marker_.get("labelStyle");
385 | for (i in labelStyle) {
386 | if (labelStyle.hasOwnProperty(i)) {
387 | this.labelDiv_.style[i] = labelStyle[i];
388 | this.eventDiv_.style[i] = labelStyle[i];
389 | }
390 | }
391 | this.setMandatoryStyles();
392 | };
393 |
394 | /**
395 | * Sets the mandatory styles to the DIV representing the label as well as to the
396 | * associated event DIV. This includes setting the DIV position, z-index, and visibility.
397 | * @private
398 | */
399 | MarkerLabel_.prototype.setMandatoryStyles = function () {
400 | this.labelDiv_.style.position = "absolute";
401 | this.labelDiv_.style.overflow = "hidden";
402 | // Make sure the opacity setting causes the desired effect on MSIE:
403 | if (typeof this.labelDiv_.style.opacity !== "undefined" && this.labelDiv_.style.opacity !== "") {
404 | this.labelDiv_.style.MsFilter = "\"progid:DXImageTransform.Microsoft.Alpha(opacity=" + (this.labelDiv_.style.opacity * 100) + ")\"";
405 | this.labelDiv_.style.filter = "alpha(opacity=" + (this.labelDiv_.style.opacity * 100) + ")";
406 | }
407 |
408 | this.eventDiv_.style.position = this.labelDiv_.style.position;
409 | this.eventDiv_.style.overflow = this.labelDiv_.style.overflow;
410 | this.eventDiv_.style.opacity = 0.01; // Don't use 0; DIV won't be clickable on MSIE
411 | this.eventDiv_.style.MsFilter = "\"progid:DXImageTransform.Microsoft.Alpha(opacity=1)\"";
412 | this.eventDiv_.style.filter = "alpha(opacity=1)"; // For MSIE
413 |
414 | this.setAnchor();
415 | this.setPosition(); // This also updates z-index, if necessary.
416 | this.setVisible();
417 | };
418 |
419 | /**
420 | * Sets the anchor point of the label.
421 | * @private
422 | */
423 | MarkerLabel_.prototype.setAnchor = function () {
424 | var anchor = this.marker_.get("labelAnchor");
425 | this.labelDiv_.style.marginLeft = -anchor.x + "px";
426 | this.labelDiv_.style.marginTop = -anchor.y + "px";
427 | this.eventDiv_.style.marginLeft = -anchor.x + "px";
428 | this.eventDiv_.style.marginTop = -anchor.y + "px";
429 | };
430 |
431 | /**
432 | * Sets the position of the label. The z-index is also updated, if necessary.
433 | * @private
434 | */
435 | MarkerLabel_.prototype.setPosition = function (yOffset) {
436 | var position = this.getProjection().fromLatLngToDivPixel(this.marker_.getPosition());
437 | if (typeof yOffset === "undefined") {
438 | yOffset = 0;
439 | }
440 | this.labelDiv_.style.left = Math.round(position.x) + "px";
441 | this.labelDiv_.style.top = Math.round(position.y - yOffset) + "px";
442 | this.eventDiv_.style.left = this.labelDiv_.style.left;
443 | this.eventDiv_.style.top = this.labelDiv_.style.top;
444 |
445 | this.setZIndex();
446 | };
447 |
448 | /**
449 | * Sets the z-index of the label. If the marker's z-index property has not been defined, the z-index
450 | * of the label is set to the vertical coordinate of the label. This is in keeping with the default
451 | * stacking order for Google Maps: markers to the south are in front of markers to the north.
452 | * @private
453 | */
454 | MarkerLabel_.prototype.setZIndex = function () {
455 | var zAdjust = (this.marker_.get("labelInBackground") ? -1 : +1);
456 | if (typeof this.marker_.getZIndex() === "undefined") {
457 | this.labelDiv_.style.zIndex = parseInt(this.labelDiv_.style.top, 10) + zAdjust;
458 | this.eventDiv_.style.zIndex = this.labelDiv_.style.zIndex;
459 | } else {
460 | this.labelDiv_.style.zIndex = this.marker_.getZIndex() + zAdjust;
461 | this.eventDiv_.style.zIndex = this.labelDiv_.style.zIndex;
462 | }
463 | };
464 |
465 | /**
466 | * Sets the visibility of the label. The label is visible only if the marker itself is
467 | * visible (i.e., its visible property is true) and the labelVisible property is true.
468 | * @private
469 | */
470 | MarkerLabel_.prototype.setVisible = function () {
471 | if (this.marker_.get("labelVisible")) {
472 | this.labelDiv_.style.display = this.marker_.getVisible() ? "block" : "none";
473 | } else {
474 | this.labelDiv_.style.display = "none";
475 | }
476 | this.eventDiv_.style.display = this.labelDiv_.style.display;
477 | };
478 |
479 | /**
480 | * @name MarkerWithLabelOptions
481 | * @class This class represents the optional parameter passed to the {@link MarkerWithLabel} constructor.
482 | * The properties available are the same as for google.maps.Marker
with the addition
483 | * of the properties listed below. To change any of these additional properties after the labeled
484 | * marker has been created, call google.maps.Marker.set(propertyName, propertyValue)
.
485 | *
486 | * When any of these properties changes, a property changed event is fired. The names of these
487 | * events are derived from the name of the property and are of the form propertyname_changed
.
488 | * For example, if the content of the label changes, a labelcontent_changed
event
489 | * is fired.
490 | *
491 | * @property {string|Node} [labelContent] The content of the label (plain text or an HTML DOM node).
492 | * @property {Point} [labelAnchor] By default, a label is drawn with its anchor point at (0,0) so
493 | * that its top left corner is positioned at the anchor point of the associated marker. Use this
494 | * property to change the anchor point of the label. For example, to center a 50px-wide label
495 | * beneath a marker, specify a
48 |
49 | A demo app to display a list of important events in Human history based on Wikipedia data. Uses Three.js, axios and React.js Select a date range below, or read how this was builtlabelAnchor
of google.maps.Point(25, 0)
.
496 | * (Note: x-values increase to the right and y-values increase to the top.)
497 | * @property {string} [labelClass] The name of the CSS class defining the styles for the label.
498 | * Note that style values for position
, overflow
, top
,
499 | * left
, zIndex
, display
, marginLeft
, and
500 | * marginTop
are ignored; these styles are for internal use only.
501 | * @property {Object} [labelStyle] An object literal whose properties define specific CSS
502 | * style values to be applied to the label. Style values defined here override those that may
503 | * be defined in the labelClass
style sheet. If this property is changed after the
504 | * label has been created, all previously set styles (except those defined in the style sheet)
505 | * are removed from the label before the new style values are applied.
506 | * Note that style values for position
, overflow
, top
,
507 | * left
, zIndex
, display
, marginLeft
, and
508 | * marginTop
are ignored; these styles are for internal use only.
509 | * @property {boolean} [labelInBackground] A flag indicating whether a label that overlaps its
510 | * associated marker should appear in the background (i.e., in a plane below the marker).
511 | * The default is false
, which causes the label to appear in the foreground.
512 | * @property {boolean} [labelVisible] A flag indicating whether the label is to be visible.
513 | * The default is true
. Note that even if labelVisible
is
514 | * true
, the label will not be visible unless the associated marker is also
515 | * visible (i.e., unless the marker's visible
property is true
).
516 | * @property {boolean} [raiseOnDrag] A flag indicating whether the label and marker are to be
517 | * raised when the marker is dragged. The default is true
. If a draggable marker is
518 | * being created and a version of Google Maps API earlier than V3.3 is being used, this property
519 | * must be set to false
.
520 | * @property {boolean} [optimized] A flag indicating whether rendering is to be optimized for the
521 | * marker. Important: The optimized rendering technique is not supported by MarkerWithLabel,
522 | * so the value of this parameter is always forced to false
.
523 | * @property {string} [crossImage="http://maps.gstatic.com/intl/en_us/mapfiles/drag_cross_67_16.png"]
524 | * The URL of the cross image to be displayed while dragging a marker.
525 | * @property {string} [handCursor="http://maps.gstatic.com/intl/en_us/mapfiles/closedhand_8_8.cur"]
526 | * The URL of the cursor to be displayed while dragging a marker.
527 | */
528 | /**
529 | * Creates a MarkerWithLabel with the options specified in {@link MarkerWithLabelOptions}.
530 | * @constructor
531 | * @param {MarkerWithLabelOptions} [opt_options] The optional parameters.
532 | */
533 | function MarkerWithLabel(opt_options) {
534 | opt_options = opt_options || {};
535 | opt_options.labelContent = opt_options.labelContent || "";
536 | opt_options.labelAnchor = opt_options.labelAnchor || new google.maps.Point(0, 0);
537 | opt_options.labelClass = opt_options.labelClass || "markerLabels";
538 | opt_options.labelStyle = opt_options.labelStyle || {};
539 | opt_options.labelInBackground = opt_options.labelInBackground || false;
540 | if (typeof opt_options.labelVisible === "undefined") {
541 | opt_options.labelVisible = true;
542 | }
543 | if (typeof opt_options.raiseOnDrag === "undefined") {
544 | opt_options.raiseOnDrag = true;
545 | }
546 | if (typeof opt_options.clickable === "undefined") {
547 | opt_options.clickable = true;
548 | }
549 | if (typeof opt_options.draggable === "undefined") {
550 | opt_options.draggable = false;
551 | }
552 | if (typeof opt_options.optimized === "undefined") {
553 | opt_options.optimized = false;
554 | }
555 | opt_options.crossImage = opt_options.crossImage || "http" + (document.location.protocol === "https:" ? "s" : "") + "://maps.gstatic.com/intl/en_us/mapfiles/drag_cross_67_16.png";
556 | opt_options.handCursor = opt_options.handCursor || "http" + (document.location.protocol === "https:" ? "s" : "") + "://maps.gstatic.com/intl/en_us/mapfiles/closedhand_8_8.cur";
557 | opt_options.optimized = false; // Optimized rendering is not supported
558 |
559 | this.label = new MarkerLabel_(this, opt_options.crossImage, opt_options.handCursor); // Bind the label to the marker
560 |
561 | // Call the parent constructor. It calls Marker.setValues to initialize, so all
562 | // the new parameters are conveniently saved and can be accessed with get/set.
563 | // Marker.set triggers a property changed event (called "propertyname_changed")
564 | // that the marker label listens for in order to react to state changes.
565 | google.maps.Marker.apply(this, arguments);
566 | }
567 |
568 | inherits(MarkerWithLabel, google.maps.Marker);
569 |
570 | /**
571 | * Overrides the standard Marker setMap function.
572 | * @param {Map} theMap The map to which the marker is to be added.
573 | * @private
574 | */
575 | MarkerWithLabel.prototype.setMap = function (theMap) {
576 |
577 | // Call the inherited function...
578 | google.maps.Marker.prototype.setMap.apply(this, arguments);
579 |
580 | // ... then deal with the label:
581 | this.label.setMap(theMap);
582 | };
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | require("babel-core/register")({ presets: ['es2015', 'react', 'stage-1'] })
2 |
3 | var express = require('express'),
4 | path = require('path'),
5 | app = express(),
6 | ip = '0.0.0.0',
7 | port = 3000,
8 | bodyParser = require('body-parser')
9 |
10 | // Include static assets
11 | app.use(express.static(path.join(__dirname, 'public')));
12 |
13 | app.set('views', path.join(__dirname, 'views'));
14 | app.set('view engine', 'ejs');
15 |
16 | // Set up routing
17 | require('./app/routes/core-routes.js')(app);
18 |
19 | // Set 404
20 | app.get('*', function(req, res) {
21 | res.json({
22 | "route": "Sorry this page does not exist!"
23 | });
24 | });
25 |
26 | app.listen(port, ip);
27 |
28 | console.log('Server is Up and Running at Port : ' + port);
--------------------------------------------------------------------------------
/views/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
50 |
51 |
A History of Modern Humanity
61 |
The Post-Industrial Revolution World