diff --git a/src/public/.htaccess b/app/.htaccess similarity index 100% rename from src/public/.htaccess rename to app/.htaccess diff --git a/src/public/404.html b/app/404.html similarity index 100% rename from src/public/404.html rename to app/404.html diff --git a/src/public/css/main.css b/app/css/main.css similarity index 100% rename from src/public/css/main.css rename to app/css/main.css diff --git a/src/public/favicon.ico b/app/favicon.ico similarity index 100% rename from src/public/favicon.ico rename to app/favicon.ico diff --git a/src/public/humans.txt b/app/humans.txt similarity index 100% rename from src/public/humans.txt rename to app/humans.txt diff --git a/src/public/icon.png b/app/icon.png similarity index 100% rename from src/public/icon.png rename to app/icon.png diff --git a/src/public/index.html b/app/index.html similarity index 94% rename from src/public/index.html rename to app/index.html index e7d352a..2fa3113 100644 --- a/src/public/index.html +++ b/app/index.html @@ -9,6 +9,7 @@ + diff --git a/src/public/js/app.js b/app/js/app.js similarity index 100% rename from src/public/js/app.js rename to app/js/app.js diff --git a/src/public/robots.txt b/app/robots.txt similarity index 100% rename from src/public/robots.txt rename to app/robots.txt diff --git a/src/public/site.webmanifest b/app/site.webmanifest similarity index 100% rename from src/public/site.webmanifest rename to app/site.webmanifest diff --git a/src/public/tags/home.tag.html b/app/tags/home.tag.html similarity index 91% rename from src/public/tags/home.tag.html rename to app/tags/home.tag.html index f7562cc..8caae5a 100644 --- a/src/public/tags/home.tag.html +++ b/app/tags/home.tag.html @@ -5,7 +5,7 @@ Built your next revolutionary Single Page Application (SPA) starting right here: -
/public/tags/home.tag.html+
/app/tags/home.tag.htmlThis seed kicks your development into high gear with all tools you'll need, and very little you don't. diff --git a/src/public/tags/layout/footer.tag.html b/app/tags/layout/footer.tag.html similarity index 100% rename from src/public/tags/layout/footer.tag.html rename to app/tags/layout/footer.tag.html diff --git a/src/public/tags/layout/header.tag.html b/app/tags/layout/header.tag.html similarity index 100% rename from src/public/tags/layout/header.tag.html rename to app/tags/layout/header.tag.html diff --git a/src/public/vendor/.gitkeep b/app/vendor/.gitkeep similarity index 100% rename from src/public/vendor/.gitkeep rename to app/vendor/.gitkeep diff --git a/app/vendor/grayscale/grayscale.css b/app/vendor/grayscale/grayscale.css new file mode 100644 index 0000000..4039d75 --- /dev/null +++ b/app/vendor/grayscale/grayscale.css @@ -0,0 +1,630 @@ +/* Grayscale.css v:0.8.1 | MIT LICENSE | https://github.com/n2geoff/grayscale */ + +/* CSS Reset */ + +html { + box-sizing: border-box; + font-family: georgia, serif; + font-size: 16px; + line-height: 1.4em; + color: #2A2A2A; + -webkit-font-smoothing: antialiased; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +html, +body { + height: 100%; +} + +body, +html, +span, +div { + margin: 0; + padding: 0; + font-weight: normal; +} + +ol, +ul { + list-style: none; +} + +img, +embed, +iframe, +object, +audio, +video { + height: auto; + max-width: 100%; + border: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +/* Blockquote */ + +.blockquote, +.quote { + border-left: 0.4em solid #E6E6E6; + background-color: #F9F9F9; + margin-left: 0; + margin-right: 0; + padding: 1em 1.5em; +} + +.blockquote *:last-child, +.quote *:last-child { + margin: 0; +} + +/* Buttons */ + +.button, +a.button, +.button[type="submit"], +.button[type="reset"], +.button[type="button"] { + position: relative; + zoom: 1; + line-height: normal; + margin: 0; + white-space: nowrap; + vertical-align: top; + text-align: center; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + box-sizing: border-box; + font-family: inherit; + font-size: 1em; + padding: .5em 1em; + background-color: #F9F9F9; + text-decoration: none; + border: 1px solid #c6c6c6; +} + +.button.is-link { + color: #101111; + border-color: transparent; + background-color: transparent; + text-decoration: none; +} + +.button.is-link:hover { + background-image: none; + text-decoration: underline; +} + +.button.is-rounded { + border-radius: 5px; +} + +.button:hover, +.button[type="submit"]:hover, +.button[type="reset"]:hover, +.button[type="button"]:hover { + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(0,0,0,0)', endColorstr='#1a000000',GradientType=0); + background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10)); +} + +.button:active, +.button[type="submit"]:active, +.button[type="reset"]:active, +.button[type="button"]:active { + box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset; + border-color: #000; +} + +.button:focus, +.button[type="submit"]:focus, +.button[type="reset"]:focus, +.button[type="button"]:focus { + outline: 0; +} + +.is-disabled, +.is-disabled:hover, +.is-disabled:active, +.is-disabled:focus { + border: 1px solid #c6c6c6; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.40; + cursor: not-allowed; + box-shadow: none; +} + +a.button, +a.button:active, +a.button:visited { + display: inline-block; + color: inherit; +} + +/* Card Component */ + +.card { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + overflow: hidden; + -webkit-box-flex: 0; + -ms-flex: 0 1 calc(50% - 0.5em); + flex: 0 1 calc(50% - 0.5em); + margin-bottom: 1em; +} + +.card-header { + font-weight: bold; + margin: 0; + padding: .5em; +} + +.card-content { + padding: 1em .5em; + min-height: 100px; +} + +.card-footer { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + border-top: 1px solid #dbdbdb; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; +} + +.card-footer .card-footer-item { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -ms-flex: 1 0 0; + flex: 1 0 0; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin: 0; + padding: 1em; +} + +.card.is-shadowed { + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); +} + +/* Forms */ + +.field, +.textarea { + font-size: 1em; + height: 36px; + width: 100%; + padding: 6px 10px; + /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #F9F9F9; + border: 1px solid #E6E6E6; + box-shadow: none; + box-sizing: border-box; +} + +.textarea { + min-height: 6em; + padding-top: 6px; + padding-bottom: 6px; +} + +.field[type="checkbox"], +.field[type="radio"] { + position: relative; + bottom: -3px; + height: 16px; + width: 16px; +} + +.field:hover, +.textarea:hover { + border: 1px solid #c6c6c6; + outline: 0; +} + +.field:focus, +.textarea:focus { + border: 1px solid #787878; + background-color: #FFF; + outline: 0; +} + +.field-group, +.group { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-pack: distribute; + justify-content: space-around; +} + +.stack { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} + +.addon { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + padding: 0 1em; + line-height: 2em; + vertical-align: middle; +} + +.label, +.legend { + display: block; + padding: 0.5em 0; + font-weight: 600; +} + +.fieldset { + margin: .5em; + padding: 0; + border-width: 0; +} + +/* Layout Container */ + +.layout { + margin: 0 auto; + zoom: 1; + letter-spacing: normal; + word-spacing: normal; + vertical-align: top; + text-rendering: auto; +} + +.container { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + -ms-flex-line-pack: stretch; + align-content: stretch; + height: 100%; +} + +.page { + width: 90%; + max-width: 1140px; + margin: 0 auto; +} + +/* Flex-Based Grid Solution */ + +.row { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; +} + +.column { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; +} + +.expand { + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; +} + +/* Precent-Based Grid Solution */ + +.column-100, +.column-20, +.column-25, +.column-33, +.column-50, +.column-67 { + display: inline; + box-sizing: border-box; + *margin-left: -0.04em; +} + +.column-20 { + width: 20%; +} + +.column-25 { + width: 25%; +} + +.column-33 { + width: 33.33%; +} + +.column-50 { + width: 50%; +} + +.column-67 { + width: 67.67%; +} + +.column-100 { + width: 100%; +} + +/* Navigation */ + +.navbar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; +} + +.navbar-item { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + margin: 0 .5em; + -webkit-box-align: bottom; + -ms-flex-align: bottom; + align-items: bottom; +} + +/* Tables */ + +.table { + width: 100%; + border-spacing: 0; +} + +.table thead tr th { + border-bottom: 2px solid #c6c6c6; +} + +.table th, +.table td { + padding: .5em 0; + text-align: left; + border-bottom: 1px solid #c6c6c6; +} + +.table tr th:first-child, +.table tr td:first-child { + padding-left: .5em; +} + +.table.is-striped tbody tr:nth-child(odd) { + background-color: #E6E6E6; +} + +.table.is-condensed th, +table.is-condensed td { + padding: 0; +} + +.table.is-bordered td { + border: 1px solid #E6E6E6; +} + +.table.is-bordered th { + border: 1px solid #E6E6E6; + border-bottom: 2px solid #E6E6E6; +} + +/* Typeography */ + +p { + line-height: 1.4em; + margin-top: 1.4em; +} + +/* Utilities */ + +.is-right { + float: right; +} + +.is-left { + float: left; +} + +.is-centered { + margin: auto; + text-align: center; +} + +.is-inline { + display: inline; +} + +.is-block { + display: block; +} + +.is-bordered { + border: 1px solid #E6E6E6; +} + +.is-divider, +hr { + border-top: 1px solid #E6E6E6; + border-top: 1px solid #E6E6E6; +} + +.is-well { + padding: 1em; +} + +.is-wall { + padding: 0 .5em 0 .5em; +} + +.is-wide { + width: 100%; + margin: inherit 0; +} + +.is-tall { + height: 100%; + margin: 0 inherit; +} + +.is-fit { + height: 100%; + width: 100%; + margin: 0; +} + +.is-borderless { + border: none; +} + +.is-clear { + clear: both; +} + +.is-small { + font-size: .8em; +} + +.is-large { + font-size: 1.2em; +} + +.is-hidden { + display: none; +} + +.is-upper { + text-transform: uppercase; +} + +.is-lower { + text-transform: lowercase; +} + +.is-title { + text-transform: capitalize; +} + +.is-indented { + margin-left: 1em; +} + +.is-muted { + color: #c6c6c6; +} + +/* Grayscale */ + +.is-white { + background-color: #FFF; + color: #2A2A2A; +} + +.is-lightest { + background-color: #F9F9F9; + color: #2A2A2A; +} + +.is-lighter { + background-color: #E6E6E6; + color: #2A2A2A; +} + +.is-light { + background-color: #c6c6c6; + color: #2A2A2A; +} + +.is-gray { + background-color: #acacac; + color: #101111; +} + +.is-dark { + background-color: #787878; + color: #F9F9F9; +} + +.is-darker { + background-color: #545454; + color: #F9F9F9; +} + +.is-darkest { + background-color: #2A2A2A; + color: #F9F9F9; +} + +.is-black { + background-color: #101111; + color: #F9F9F9; +} \ No newline at end of file diff --git a/app/vendor/grayscale/grayscale.min.css b/app/vendor/grayscale/grayscale.min.css new file mode 100644 index 0000000..cd3d27c --- /dev/null +++ b/app/vendor/grayscale/grayscale.min.css @@ -0,0 +1 @@ +html{box-sizing:border-box;font-family:georgia,serif;font-size:16px;line-height:1.4em;color:#2a2a2a;-webkit-font-smoothing:antialiased}*,:after,:before{box-sizing:inherit}body,html{height:100%}body,div,html,span{margin:0;padding:0;font-weight:400}ol,ul{list-style:none}audio,embed,iframe,img,object,video{height:auto;max-width:100%;border:none}table{border-collapse:collapse;border-spacing:0}.blockquote,.quote{border-left:.4em solid #e6e6e6;background-color:#f9f9f9;margin-left:0;margin-right:0;padding:1em 1.5em}.blockquote :last-child,.quote :last-child{margin:0}.button,.button[type=button],.button[type=reset],.button[type=submit],a.button{position:relative;zoom:1;line-height:normal;margin:0;white-space:nowrap;vertical-align:top;text-align:center;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box;font-family:inherit;font-size:1em;padding:.5em 1em;background-color:#f9f9f9;text-decoration:none;border:1px solid #c6c6c6}.button.is-link{color:#101111;border-color:transparent;background-color:transparent;text-decoration:none}.button.is-link:hover{background-image:none;text-decoration:underline}.button.is-rounded{border-radius:5px}.button:hover,.button[type=button]:hover,.button[type=reset]:hover,.button[type=submit]:hover{background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.button:active,.button[type=button]:active,.button[type=reset]:active,.button[type=submit]:active{box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.button:focus,.button[type=button]:focus,.button[type=reset]:focus,.button[type=submit]:focus{outline:0}.is-disabled,.is-disabled:active,.is-disabled:focus,.is-disabled:hover{border:1px solid #c6c6c6;background-image:none;opacity:.4;cursor:not-allowed;box-shadow:none}a.button,a.button:active,a.button:visited{display:inline-block;color:inherit}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;overflow:hidden;-webkit-box-flex:0;-ms-flex:0 1 calc(50% - .5em);flex:0 1 calc(50% - .5em);margin-bottom:1em}.card-header{font-weight:700;margin:0;padding:.5em}.card-content{padding:1em .5em;min-height:100px}.card-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;border-top:1px solid #dbdbdb;-webkit-box-flex:1;-ms-flex:1;flex:1}.card-footer .card-footer-item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 0 0;flex:1 0 0;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:0;padding:1em}.card.is-shadowed{box-shadow:0 5px 15px rgba(0,0,0,.1)}.field,.textarea{font-size:1em;height:36px;width:100%;padding:6px 10px;background-color:#f9f9f9;border:1px solid #e6e6e6;box-shadow:none;box-sizing:border-box}.textarea{min-height:6em;padding-top:6px;padding-bottom:6px}.field[type=checkbox],.field[type=radio]{position:relative;bottom:-3px;height:16px;width:16px}.field:hover,.textarea:hover{border:1px solid #c6c6c6;outline:0}.field:focus,.textarea:focus{border:1px solid #787878;background-color:#fff;outline:0}.field-group,.group{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-pack:distribute;justify-content:space-around}.stack{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.addon{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;padding:0 1em;line-height:2em;vertical-align:middle}.label,.legend{display:block;padding:.5em 0;font-weight:600}.fieldset{margin:.5em;padding:0;border-width:0}.layout{margin:0 auto;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-ms-flex-line-pack:stretch;align-content:stretch;height:100%}.page{width:90%;max-width:1140px;margin:0 auto}.row{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.column{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-flex:1;-ms-flex:1;flex:1}.expand{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.column-100,.column-20,.column-25,.column-33,.column-50,.column-67{display:inline;box-sizing:border-box}.column-20{width:20%}.column-25{width:25%}.column-33{width:33.33%}.column-50{width:50%}.column-67{width:67.67%}.column-100{width:100%}.navbar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;margin:0 .5em;-webkit-box-align:bottom;-ms-flex-align:bottom;align-items:bottom}.table{width:100%;border-spacing:0}.table thead tr th{border-bottom:2px solid #c6c6c6}.table td,.table th{padding:.5em 0;text-align:left;border-bottom:1px solid #c6c6c6}.table tr td:first-child,.table tr th:first-child{padding-left:.5em}.table.is-striped tbody tr:nth-child(odd){background-color:#e6e6e6}.table.is-condensed th,table.is-condensed td{padding:0}.table.is-bordered td{border:1px solid #e6e6e6}.table.is-bordered th{border:1px solid #e6e6e6;border-bottom:2px solid #e6e6e6}p{line-height:1.4em;margin-top:1.4em}.is-right{float:right}.is-left{float:left}.is-centered{margin:auto;text-align:center}.is-inline{display:inline}.is-block{display:block}.is-bordered{border:1px solid #e6e6e6}.is-divider,hr{border-top:1px solid #e6e6e6;border-top:1px solid #e6e6e6}.is-well{padding:1em}.is-wall{padding:0 .5em 0 .5em}.is-wide{width:100%;margin:inherit 0}.is-tall{height:100%;margin:0 inherit}.is-fit{height:100%;width:100%;margin:0}.is-borderless{border:none}.is-clear{clear:both}.is-small{font-size:.8em}.is-large{font-size:1.2em}.is-hidden{display:none}.is-upper{text-transform:uppercase}.is-lower{text-transform:lowercase}.is-title{text-transform:capitalize}.is-indented{margin-left:1em}.is-muted{color:#c6c6c6}.is-white{background-color:#fff;color:#2a2a2a}.is-lightest{background-color:#f9f9f9;color:#2a2a2a}.is-lighter{background-color:#e6e6e6;color:#2a2a2a}.is-light{background-color:#c6c6c6;color:#2a2a2a}.is-gray{background-color:#acacac;color:#101111}.is-dark{background-color:#787878;color:#f9f9f9}.is-darker{background-color:#545454;color:#f9f9f9}.is-darkest{background-color:#2a2a2a;color:#f9f9f9}.is-black{background-color:#101111;color:#f9f9f9} \ No newline at end of file diff --git a/app/vendor/grayscale/theme.css b/app/vendor/grayscale/theme.css new file mode 100644 index 0000000..0fcf734 --- /dev/null +++ b/app/vendor/grayscale/theme.css @@ -0,0 +1,8 @@ +/* Colors */ + +.is-primary {background-color: steelblue; color: #F9F9F9;} +.is-secondary {background-color: #264863; color: #F9F9F9;} +.is-accent {background-color: lightsteelblue; color: #2A2A2A;} +.is-dangerous {background-color: indianred; color: #F9F9F9;} +.is-safe {background-color: darkseagreen; color: #2A2A2A;} +.is-warning {background-color: khaki; color: #2A2A2A;} diff --git a/app/vendor/riot-route/route.js b/app/vendor/riot-route/route.js new file mode 100644 index 0000000..e86d297 --- /dev/null +++ b/app/vendor/riot-route/route.js @@ -0,0 +1,486 @@ +var route = (function () { + 'use strict'; + + var observable = function(el) { + + /** + * Extend the original object or create a new empty one + * @type { Object } + */ + + el = el || {}; + + /** + * Private variables + */ + var callbacks = {}, + slice = Array.prototype.slice; + + /** + * Public Api + */ + + // extend the el object adding the observable methods + Object.defineProperties(el, { + /** + * Listen to the given `event` ands + * execute the `callback` each time an event is triggered. + * @param { String } event - event id + * @param { Function } fn - callback function + * @returns { Object } el + */ + on: { + value: function(event, fn) { + if (typeof fn == 'function') + { (callbacks[event] = callbacks[event] || []).push(fn); } + return el + }, + enumerable: false, + writable: false, + configurable: false + }, + + /** + * Removes the given `event` listeners + * @param { String } event - event id + * @param { Function } fn - callback function + * @returns { Object } el + */ + off: { + value: function(event, fn) { + if (event == '*' && !fn) { callbacks = {}; } + else { + if (fn) { + var arr = callbacks[event]; + for (var i = 0, cb; cb = arr && arr[i]; ++i) { + if (cb == fn) { arr.splice(i--, 1); } + } + } else { delete callbacks[event]; } + } + return el + }, + enumerable: false, + writable: false, + configurable: false + }, + + /** + * Listen to the given `event` and + * execute the `callback` at most once + * @param { String } event - event id + * @param { Function } fn - callback function + * @returns { Object } el + */ + one: { + value: function(event, fn) { + function on() { + el.off(event, on); + fn.apply(el, arguments); + } + return el.on(event, on) + }, + enumerable: false, + writable: false, + configurable: false + }, + + /** + * Execute all callback functions that listen to + * the given `event` + * @param { String } event - event id + * @returns { Object } el + */ + trigger: { + value: function(event) { + var arguments$1 = arguments; + + + // getting the arguments + var arglen = arguments.length - 1, + args = new Array(arglen), + fns, + fn, + i; + + for (i = 0; i < arglen; i++) { + args[i] = arguments$1[i + 1]; // skip first argument + } + + fns = slice.call(callbacks[event] || [], 0); + + for (i = 0; fn = fns[i]; ++i) { + fn.apply(el, args); + } + + if (callbacks['*'] && event != '*') + { el.trigger.apply(el, ['*', event].concat(args)); } + + return el + }, + enumerable: false, + writable: false, + configurable: false + } + }); + + return el + + }; + + /** + * Simple client-side router + * @module riot-route + */ + + var RE_ORIGIN = /^.+?\/\/+[^/]+/, + EVENT_LISTENER = 'EventListener', + REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER, + ADD_EVENT_LISTENER = 'add' + EVENT_LISTENER, + HAS_ATTRIBUTE = 'hasAttribute', + POPSTATE = 'popstate', + HASHCHANGE = 'hashchange', + TRIGGER = 'trigger', + MAX_EMIT_STACK_LEVEL = 3, + win = typeof window != 'undefined' && window, + doc = typeof document != 'undefined' && document, + hist = win && history, + loc = win && (hist.location || win.location), // see html5-history-api + prot = Router.prototype, // to minify more + clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click', + central = observable(); + + var + started = false, + routeFound = false, + debouncedEmit, + current, + parser, + secondParser, + emitStack = [], + emitStackLevel = 0; + + /** + * Default parser. You can replace it via router.parser method. + * @param {string} path - current path (normalized) + * @returns {array} array + */ + function DEFAULT_PARSER(path) { + return path.split(/[/?#]/) + } + + /** + * Default parser (second). You can replace it via router.parser method. + * @param {string} path - current path (normalized) + * @param {string} filter - filter string (normalized) + * @returns {array} array + */ + function DEFAULT_SECOND_PARSER(path, filter) { + var f = filter + .replace(/\?/g, '\\?') + .replace(/\*/g, '([^/?#]+?)') + .replace(/\.\./, '.*'); + var re = new RegExp(("^" + f + "$")); + var args = path.match(re); + + if (args) { return args.slice(1) } + } + + /** + * Simple/cheap debounce implementation + * @param {function} fn - callback + * @param {number} delay - delay in seconds + * @returns {function} debounced function + */ + function debounce(fn, delay) { + var t; + return function () { + clearTimeout(t); + t = setTimeout(fn, delay); + } + } + + /** + * Set the window listeners to trigger the routes + * @param {boolean} autoExec - see route.start + */ + function start(autoExec) { + debouncedEmit = debounce(emit, 1); + win[ADD_EVENT_LISTENER](POPSTATE, debouncedEmit); + win[ADD_EVENT_LISTENER](HASHCHANGE, debouncedEmit); + doc[ADD_EVENT_LISTENER](clickEvent, click); + + if (autoExec) { emit(true); } + } + + /** + * Router class + */ + function Router() { + this.$ = []; + observable(this); // make it observable + central.on('stop', this.s.bind(this)); + central.on('emit', this.e.bind(this)); + } + + function normalize(path) { + return path.replace(/^\/|\/$/, '') + } + + function isString(str) { + return typeof str == 'string' + } + + /** + * Get the part after domain name + * @param {string} href - fullpath + * @returns {string} path from root + */ + function getPathFromRoot(href) { + return (href || loc.href).replace(RE_ORIGIN, '') + } + + /** + * Get the part after base + * @param {string} href - fullpath + * @returns {string} path from base + */ + function getPathFromBase(href) { + var base = route._.base; + return base[0] === '#' + ? (href || loc.href || '').split(base)[1] || '' + : (loc ? getPathFromRoot(href) : href || '').replace(base, '') + } + + function emit(force) { + // the stack is needed for redirections + var isRoot = emitStackLevel === 0; + if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) { return } + + emitStackLevel++; + emitStack.push(function() { + var path = getPathFromBase(); + if (force || path !== current) { + central[TRIGGER]('emit', path); + current = path; + } + }); + + if (isRoot) { + var first; + while (first = emitStack.shift()) { first(); } // stack increses within this call + emitStackLevel = 0; + } + } + + function click(e) { + if ( + e.which !== 1 // not left click + || e.metaKey || e.ctrlKey || e.shiftKey // or meta keys + || e.defaultPrevented // or default prevented + ) { return } + + var el = e.target; + while (el && el.nodeName !== 'A') { el = el.parentNode; } + + if ( + !el || el.nodeName !== 'A' // not A tag + || el[HAS_ATTRIBUTE]('download') // has download attr + || !el[HAS_ATTRIBUTE]('href') // has no href attr + || el.target && el.target !== '_self' // another window or frame + || el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) === -1 // cross origin + ) { return } + + var base = route._.base; + + if (el.href !== loc.href + && ( + el.href.split('#')[0] === loc.href.split('#')[0] // internal jump + || base[0] !== '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base + || base[0] === '#' && el.href.split(base)[0] !== loc.href.split(base)[0] // outside of #base + || !go(getPathFromBase(el.href), el.title || doc.title) // route not found + )) { return } + + e.preventDefault(); + } + + /** + * Go to the path + * @param {string} path - destination path + * @param {string} title - page title + * @param {boolean} shouldReplace - use replaceState or pushState + * @returns {boolean} - route not found flag + */ + function go(path, title, shouldReplace) { + // Server-side usage: directly execute handlers for the path + if (!hist) { return central[TRIGGER]('emit', getPathFromBase(path)) } + + path = route._.base + normalize(path); + title = title || doc.title; + // browsers ignores the second parameter `title` + shouldReplace + ? hist.replaceState(null, title, path) + : hist.pushState(null, title, path); + // so we need to set it manually + doc.title = title; + routeFound = false; + emit(); + return routeFound + } + + /** + * Go to path or set action + * a single string: go there + * two strings: go there with setting a title + * two strings and boolean: replace history with setting a title + * a single function: set an action on the default route + * a string/RegExp and a function: set an action on the route + * @param {(string|function)} first - path / action / filter + * @param {(string|RegExp|function)} second - title / action + * @param {boolean} third - replace flag + */ + prot.m = function(first, second, third) { + if (isString(first) && (!second || isString(second))) { go(first, second, third || false); } + else if (second) { this.r(first, second); } + else { this.r('@', first); } + }; + + /** + * Stop routing + */ + prot.s = function() { + this.off('*'); + this.$ = []; + }; + + /** + * Emit + * @param {string} path - path + */ + prot.e = function(path) { + this.$.concat('@').some(function(filter) { + var args = (filter === '@' ? parser : secondParser)(normalize(path), normalize(filter)); + if (typeof args != 'undefined') { + this[TRIGGER].apply(null, [filter].concat(args)); + return routeFound = true // exit from loop + } + }, this); + }; + + /** + * Register route + * @param {string} filter - filter for matching to url + * @param {function} action - action to register + */ + prot.r = function(filter, action) { + if (filter !== '@') { + filter = '/' + normalize(filter); + this.$.push(filter); + } + + this.on(filter, action); + }; + + var mainRouter = new Router(); + var route = mainRouter.m.bind(mainRouter); + + // adding base and getPathFromBase to route so we can access them in route.tag's script + route._ = { base: null, getPathFromBase: getPathFromBase }; + + /** + * Create a sub router + * @returns {function} the method of a new Router object + */ + route.create = function() { + var newSubRouter = new Router(); + // assign sub-router's main method + var router = newSubRouter.m.bind(newSubRouter); + // stop only this sub-router + router.stop = newSubRouter.s.bind(newSubRouter); + return router + }; + + /** + * Set the base of url + * @param {(str|RegExp)} arg - a new base or '#' or '#!' + */ + route.base = function(arg) { + route._.base = arg || '#'; + current = getPathFromBase(); // recalculate current path + }; + + /** Exec routing right now **/ + route.exec = function() { + emit(true); + }; + + /** + * Replace the default router to yours + * @param {function} fn - your parser function + * @param {function} fn2 - your secondParser function + */ + route.parser = function(fn, fn2) { + if (!fn && !fn2) { + // reset parser for testing... + parser = DEFAULT_PARSER; + secondParser = DEFAULT_SECOND_PARSER; + } + if (fn) { parser = fn; } + if (fn2) { secondParser = fn2; } + }; + + /** + * Helper function to get url query as an object + * @returns {object} parsed query + */ + route.query = function() { + var q = {}; + var href = loc.href || current; + href.replace(/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v; }); + return q + }; + + /** Stop routing **/ + route.stop = function () { + if (started) { + if (win) { + win[REMOVE_EVENT_LISTENER](POPSTATE, debouncedEmit); + win[REMOVE_EVENT_LISTENER](HASHCHANGE, debouncedEmit); + doc[REMOVE_EVENT_LISTENER](clickEvent, click); + } + + central[TRIGGER]('stop'); + started = false; + } + }; + + /** + * Start routing + * @param {boolean} autoExec - automatically exec after starting if true + */ + route.start = function (autoExec) { + if (!started) { + if (win) { + if (document.readyState === 'interactive' || document.readyState === 'complete') { + start(autoExec); + } else { + document.onreadystatechange = function () { + if (document.readyState === 'interactive') { + // the timeout is needed to solve + // a weird safari bug https://github.com/riot/route/issues/33 + setTimeout(function() { start(autoExec); }, 1); + } + }; + } + } + + started = true; + } + }; + + /** Prepare the router **/ + route.base(); + route.parser(); + + return route; + +}()); diff --git a/app/vendor/riot-route/route.min.js b/app/vendor/riot-route/route.min.js new file mode 100644 index 0000000..109a031 --- /dev/null +++ b/app/vendor/riot-route/route.min.js @@ -0,0 +1 @@ +var route=function(){"use strict";var e=function(u){u=u||{};var o={},l=Array.prototype.slice;Object.defineProperties(u,{on:{value:function(e,t){if(typeof t=="function"){(o[e]=o[e]||[]).push(t)}return u},enumerable:false,writable:false,configurable:false},off:{value:function(e,t){if(e=="*"&&!t){o={}}else{if(t){var n=o[e];for(var r=0,i;i=n&&n[r];++r){if(i==t){n.splice(r--,1)}}}else{delete o[e]}}return u},enumerable:false,writable:false,configurable:false},one:{value:function(e,t){function n(){u.off(e,n);t.apply(u,arguments)}return u.on(e,n)},enumerable:false,writable:false,configurable:false},trigger:{value:function(e){var t=arguments;var n=arguments.length-1,r=new Array(n),i,a,f;for(f=0;f
]*|"[^"]*")*)?>([\S\s]+?)<\/pre\s*>/gi,Kt=/^"(?:number|date(?:time)?|time|month|email|color)\b/i,Wt=/^\s*import(?!\w|(\s)?\()(?:(?:\s|[^\s'"])*)['|"].*\n?/gm,Jt=/[ \t]+$/gm,Qt=Lt(/@#\d/,"x01"),Xt=Lt(/@#(\d+)/g,"x01"),Yt="#",er="⁗",tr='"',rr="'";function nr(e){var t,r=Ut;for(1!==e.indexOf("\r")&&(e=e.replace(/\r\n?/g,"\n")),r.lastIndex=0;t=r.exec(e);)"<"===t[0][0]&&(e=RegExp.leftContext+RegExp.rightContext,r.lastIndex=t[3]+1);return e}function ir(e,t){var r,n,i,o=[];for(Ht.lastIndex=0,e=e.replace(/\s+/g," ");r=Ht.exec(e);){var s=r[1].toLowerCase(),a=r[2];a?(a[0]!==tr&&(a=tr+(a[0]===rr?a.slice(1,-1):a)+tr),"type"===s&&Kt.test(a)?n=a:(Qt.test(a)&&("value"===s&&(i=1),-1!==Dt.indexOf(s)&&(s="riot-"+s)),o.push(s+"="+a))):o.push(s)}return n&&(i&&(n=tr+t._bp[0]+rr+n.slice(1,-1)+rr+t._bp[1]+tr),o.push("type="+n)),o.join(" ")}function or(e,t,r){var n=r._bp;if(e&&n[4].test(e)){for(var i,o=t.expr&&(t.parser||t.type)?cr:0,s=P.split(e,0,n),a=1;a"+t:"",r&&(t+=" "+ir(r,i)),"<"+t+n+">"}),!t.whitespace){var r=[];/ ]/.test(e)&&(e=e.replace(Gt,function(e){return r.push(e),""})),e=e.trim().replace(/\s+/g," "),r.length&&(e=e.replace(/\u0002/g,function(){return r.shift()}))}return t.compact&&(e=e.replace(qt,"><$1")),sr(e,i).replace(Jt,"")}var ur=/^[ \t]*(((?:async|\*)\s*)?([$_A-Za-z][$\w]*))\s*\([^()]*\)\s*{/m;function lr(e){var t,r,n,i,o,s,a=[],u=RegExp,l=function(e,t){for(var r,n,i,o,s,a,u=new RegExp(Mt,"g"),l=P.skipRegex,c=0|t,p=[[]],f=[],d=u,h=d.lastIndex=c;a=d.exec(e);){if(o=a.index,s=d.lastIndex,n="",i=a[1]){if("{"===i)f.push("}");else if("}"===i){if(f.pop()!==i)throw new Error("Unexpected '}'");"`"===f[f.length-1]&&(i=f.pop())}else"/"===i&&o+1<(s=l(e,o))&&(n=e.slice(o,s));"`"===i&&(s=$t(e,s,f),n=e.slice(o,s),d=f.length?r||(r=new RegExp(Pt,"g")):u)}else"/"===(n=a[0])[0]?(n="*"===n[1]?" ":"",e=e.slice(c,o)+n+e.slice(s),s=o+n.length,n=""):2===n.length&&(n="");n&&(p[0].push(e.slice(h,o)),p.push(n),h=s),d.lastIndex=s}return p[0].push(e.slice(h)),p}(e);for(e=l.shift().join("<%>");t=e.match(ur);)a.push(u.leftContext),n=c(e=u.rightContext),i=t[1],o=t[2]||"",s=t[3],s=(r=!/^(?:if|while|for|switch|catch|function)$/.test(s))?t[0].replace(i,"this."+s+" ="+o+" function"):t[0],a.push(s,e.slice(0,n)),e=e.slice(n),r&&!/^\s*.\s*bind\b/.test(e)&&a.push(".bind(this)");return a.length&&(e=a.join("")+e),l.length&&(e=e.replace(/<%>/g,function(){return l.shift()})),e;function c(e){for(var t=/[{}]/g,r=1;r&&t.exec(e);)"{"===e[t.lastIndex-1]?++r:--r;return r?e.length:t.lastIndex}}function cr(e,t,r,n,i){return/\S/.test(e)?(r||(r=t.type),(t.parser||r&&It._req("js."+r,!0)||lr)(e,n,i).replace(/\r\n?/g,"\n").replace(Jt,"")):""}var pr=RegExp("([{}]|^)[; ]*((?:[^@ ;{}][^{}]*)?[^@ ;{}:] ?)(?={)|"+Vt,"g");function fr(e,t,r,n){var i,o;(n=n||{},r)&&("css"!==r&&(e=It._req("css."+r,!0)(t,e,n.parserOpts||{},n.url)));return e=e.replace(P.R_MLCOMMS,"").replace(/\s+/g," ").trim(),t&&(i=t,o=":scope",e=e.replace(pr,function(e,t,r){return r?(r=r.replace(/[^,]+/g,function(e){var t=e.trim();return 0===t.indexOf(i)?e:t&&"from"!==t&&"to"!==t&&"%"!==t.slice(-1)?t=t.indexOf(o)<0?i+" "+t+',[data-is="'+i+'"] '+t:t.replace(o,i)+","+t.replace(o,'[data-is="'+i+'"]'):e}),t?t+" "+r:r):e})),e}var dr=/\stype\s*=\s*(?:(['"])(.+?)\1|(\S+))/i,hr="\\s*=\\s*("+zt+"|{[^}]+}|\\S+)",mr=/\/>\n|^<(?:\/?-?[A-Za-z][-\w\xA0-\xFF]*\s*|-?[A-Za-z][-\w\xA0-\xFF]*\s+[-\w:\xA0-\xFF][\S\s]*?)>\n/;function gr(e,t){return e?(e=rr+e.replace(/\\/g,"\\\\").replace(/'/g,"\\'")+rr,t&&-1!==e.indexOf("\n")?e.replace(/\n/g,"\\n"):e):"''"}function vr(e){if(e){var t=e.match(dr);if(t=t&&(t[2]||t[3]))return t.replace("text/","")}return""}function xr(e,t){if(e){var r=e.match(RegExp("\\s"+t+hr,"i"));if(r=r&&r[1])return/^['"]/.test(r)?r.slice(1,-1):r}return""}function yr(e){var t=xr(e,"options").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'");return t?JSON.parse(t):null}var br=RegExp(/^([ \t]*)<(-?[A-Za-z][-\w\xA0-\xFF]*)(?:\s+([^'"/>]+(?:(?:@|\/[^>])[^'"/>]*)*)|\s*)?(?:\/>|>[ \t]*\n?([\S\s]*)^\1<\/\2\s*>|>(.*)<\/\2\s*>)/.source.replace("@",zt),"gim"),wr=/