Repo wipe moving to V2
This commit is contained in:
parent
a0d2903141
commit
1c0dc989e9
28 changed files with 0 additions and 15358 deletions
18
README.md
18
README.md
|
@ -1,18 +0,0 @@
|
||||||
# My Spells
|
|
||||||
...is a user friendly mobile responsive app designed to do one thing well: _View Spells_.
|
|
||||||
|
|
||||||
[Check it out on github.io](https://sharpshark28.github.io/my_spells/)!
|
|
||||||
|
|
||||||
## Systems Supported
|
|
||||||
* Dungeons & Dragons 5e
|
|
||||||
* Hackmaster 4e (WIP)
|
|
||||||
|
|
||||||
### Will you support _X_ system?
|
|
||||||
Anyone who wishes to write up spells for a system in json format matching the same syntax used by the existing systems in this repo is welcome to add their system of choice.
|
|
||||||
|
|
||||||
## For Developers
|
|
||||||
1. Clone/Fork Repo
|
|
||||||
2. `npm install`
|
|
||||||
3. `npm run develop`
|
|
||||||
|
|
||||||
You may wish to run a local http server such as [http-server](https://github.com/indexzero/http-server).
|
|
BIN
assets/.DS_Store
vendored
BIN
assets/.DS_Store
vendored
Binary file not shown.
231
assets/app.css
231
assets/app.css
|
@ -1,231 +0,0 @@
|
||||||
body {
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action=print],
|
|
||||||
.printonly {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdl-mini-footer {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 1;
|
|
||||||
padding: .5em 1em .75em 1em
|
|
||||||
}
|
|
||||||
|
|
||||||
.do-nothing {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdl-layout-title i {
|
|
||||||
position: relative;
|
|
||||||
bottom: -.125em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#empty {
|
|
||||||
padding-bottom: 100%;
|
|
||||||
text-align: center;
|
|
||||||
background: url('wand.svg') no-repeat top center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdl-layout__header .mdl-button .mdl-badge[data-badge] {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdl-layout__header .mdl-button .mdl-badge[data-badge]::after {
|
|
||||||
left: -1em;
|
|
||||||
right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdl-navigation .mdl-textfield__label i {
|
|
||||||
vertical-align: top;
|
|
||||||
font-size: 1.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdl-navigation .mdl-textfield__input {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding-left: 1em;
|
|
||||||
padding-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdl-navigation .mdl-textfield__label {
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul,
|
|
||||||
ol {
|
|
||||||
padding: 0 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-content {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-content .mdl-grid {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-content .mdl-cell {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-template=spell-details] {
|
|
||||||
transition: margin-top 500ms ease-out;
|
|
||||||
padding: 0 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#description {
|
|
||||||
margin: 0;
|
|
||||||
max-height: 13em;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#description br:last-of-type {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#description p:last-of-type {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#copy {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#details {
|
|
||||||
columns: 2;
|
|
||||||
padding: 0;
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#details strong {
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdl-layout__header [data-action-details=""] {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
z-index: 10;
|
|
||||||
height: 4rem;
|
|
||||||
width: 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdl-layout__header [data-action-details=""] i {
|
|
||||||
position: absolute;
|
|
||||||
top: 1rem;
|
|
||||||
left: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-template=spell-details] [data-action-details=""] {
|
|
||||||
position: absolute;
|
|
||||||
top: .5rem;
|
|
||||||
right: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 840px) {
|
|
||||||
.hide-phone {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-template=spell-details] {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#spell-list-container,
|
|
||||||
[data-template=spell-details] {
|
|
||||||
transition: left 250ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
#spell-list-container {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.details #spell-list-container {
|
|
||||||
left: -95%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.details #spell-list-container::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background: black;
|
|
||||||
opacity: .25;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-template=spell-details] {
|
|
||||||
position: fixed;
|
|
||||||
width: 95%;
|
|
||||||
left: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
max-height: calc(100% - 56px)
|
|
||||||
}
|
|
||||||
|
|
||||||
body.details [data-template=spell-details] {
|
|
||||||
left: 5%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.details .mdl-layout__header [data-action-details=""] {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.details .mdl-layout__header .mdl-layout__drawer-button {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.details [data-template=spell-details] [data-action-details=""] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action-details] {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action-sort],
|
|
||||||
[data-template=class-list] label,
|
|
||||||
.classes,
|
|
||||||
.spell-level,
|
|
||||||
.spell-name,
|
|
||||||
.spell-school {
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action-sort] {
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action-sort]:hover {
|
|
||||||
background: #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-action-sort] i.material-icons.mdl-list__item-icon {
|
|
||||||
position: relative;
|
|
||||||
bottom: -.25em;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
#share-url {
|
|
||||||
padding-left: 2em;
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
@media print {
|
|
||||||
body {
|
|
||||||
background: white;
|
|
||||||
font-size: 11pt;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
body > .printonly {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
body > :not(.printonly) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 1em 1em 1em 0;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
td {
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spell-description p {
|
|
||||||
font-size: 8pt;
|
|
||||||
line-height: 10pt;
|
|
||||||
margin: .75em 0;
|
|
||||||
color: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spell-description br {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#details {
|
|
||||||
font-size: 8pt;
|
|
||||||
margin: 0;
|
|
||||||
columns: 3;
|
|
||||||
padding: 0;
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
}
|
|
123
assets/wand.svg
123
assets/wand.svg
|
@ -1,123 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1"
|
|
||||||
id="svg7404" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="232 -592.3 824.9 1155"
|
|
||||||
style="enable-background:new 232 -592.3 824.9 1155;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#EDF9F7;}
|
|
||||||
.st1{fill:#7BCBBF;}
|
|
||||||
.st2{fill:#9BD8D0;}
|
|
||||||
.st3{fill:#CBE9E4;}
|
|
||||||
.st4{fill:#6EC3BB;}
|
|
||||||
.st5{fill:#FFFFFF;}
|
|
||||||
.st6{fill:#EED7B2;}
|
|
||||||
.st7{fill:#DAC4BF;}
|
|
||||||
.st8{fill:#CCDBB9;}
|
|
||||||
.st9{fill:#DBEFBE;}
|
|
||||||
.st10{fill:#D4E6BC;}
|
|
||||||
.st11{fill:#F9FBF5;}
|
|
||||||
.st12{fill:#D6C2BE;}
|
|
||||||
.st13{fill:#E0E4DD;}
|
|
||||||
.st14{fill:#B3D3C8;}
|
|
||||||
.st15{fill:#9FCABF;}
|
|
||||||
.st16{fill:#D3DBD9;}
|
|
||||||
.st17{fill:#A6C9C4;}
|
|
||||||
.st18{fill:#BCD1CD;}
|
|
||||||
.st19{fill:#92C0BB;}
|
|
||||||
.st20{fill:#DFEAE9;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M544.6-229L544.6-229L544.6-229 M501.7-241.2L501.7-241.2l-19.1,22.8l31.1,13c0.1-1.1,0.4-2.1,1.1-2.9
|
|
||||||
c1-1.2,2.4-1.8,4-1.8c1.4,0,2.9,0.5,4.1,1.5c0.9,0.7,1.5,1.6,1.9,2.6l19.4-23.3L501.7-241.2"/>
|
|
||||||
<polyline class="st1" points="474.8,-209.1 447.4,-176.2 466.8,-136.4 489.6,-163.7 465.5,-197.8 474.9,-209.1 474.8,-209.1 "/>
|
|
||||||
<path class="st2" d="M544.5-229.4l-0.2,0.2l-19.4,23.3c0.7,1.8,0.5,3.9-0.7,5.4c-0.3,0.4-0.7,0.7-1.1,0.9l21.1,32.6l19.3-23.1
|
|
||||||
L544.6-229l0,0L544.5-229.4"/>
|
|
||||||
<polyline class="st3" points="489.9,-163.8 489.7,-163.6 489.6,-163.7 466.8,-136.4 466.7,-136.2 508.6,-124.3 508.6,-124.3
|
|
||||||
527,-146.3 489.9,-163.8 "/>
|
|
||||||
<path class="st2" d="M482.6-218.4l-7.8,9.3l-9.4,11.3l24.2,34.1l0.1,0.1l0.2-0.2l-0.2-0.1l29.3-35c-1-0.2-2-0.7-2.9-1.4
|
|
||||||
c-1.6-1.3-2.4-3.3-2.3-5.1L482.6-218.4L482.6-218.4"/>
|
|
||||||
<path class="st4" d="M523.1-199.6c-0.8,0.6-1.9,0.8-2.9,0.8c-0.4,0-0.8,0-1.2-0.1l-29.3,35l0.2,0.1l37.1,17.5l8.2-9.7l9.1-10.9
|
|
||||||
L523.1-199.6"/>
|
|
||||||
<path class="st5" d="M518.9-210c-1.5,0-3,0.6-4,1.8c-0.7,0.8-1.1,1.9-1.1,2.9c-0.1,1.8,0.7,3.7,2.3,5.1c0.9,0.7,1.9,1.2,2.9,1.4
|
|
||||||
c0.4,0.1,0.8,0.1,1.2,0.1c1,0,2.1-0.3,2.9-0.8c0.4-0.3,0.7-0.6,1.1-0.9c1.2-1.5,1.4-3.5,0.7-5.4c-0.4-1-1-1.9-1.9-2.6
|
|
||||||
C521.7-209.5,520.3-210,518.9-210"/>
|
|
||||||
<path class="st6" d="M874.4,91.9c-2,9.3-4.7,18-7.1,25.7l133.5,111.7l-2.3,2.7l0,0l13.2-15.9L874.4,91.9 M577.3-176.6l2.2,53.4
|
|
||||||
L624-86.1c4.1-1.9,9-2.9,14.2-2.9c3.2,0,6.5,0.4,9.6,1.2c13,3.4,19.8,12.9,15,21.2c-0.3,0.5-0.6,1-1,1.5c-0.7,2.4-1.5,5.5-2.1,8.9
|
|
||||||
L839.8,94.6c0-0.9,0-1.9-0.1-2.8l0,0c0,0,0,0,0,0c0.3-13.5,2-27.5-1.3-32.3L577.3-176.6"/>
|
|
||||||
<path class="st7" d="M867.3,117.6c-2.8,8.9-5.1,16.4-5.1,21.9c-0.1,3.7,0.4,6.8,1.2,9.5L987.6,245l10.9-13.1l2.3-2.7L867.3,117.6
|
|
||||||
M659.7-56.2c-3,16.4-2.7,42.8,21.9,63.4c2.2,1.8,4.6,3.4,7,4.5l67.1,52.1l0,0c-0.5,0.2-1,0.4-1.5,0.7l87.3,67.6
|
|
||||||
c-0.9-10.2-1.3-22.6-1.7-37.4L659.7-56.2 M579.6-123.3l0.1,2.5l-55.1,7.4L614-44.1c-0.6-5.7-0.7-10.8-0.7-15
|
|
||||||
c0-8.5,0.7-13.6,0.7-13.6s0-0.1,0.1-0.3c-0.1-2,0.4-4,1.5-6c1.7-3,4.7-5.4,8.4-7.1L579.6-123.3"/>
|
|
||||||
<path class="st8" d="M839.8,91.7L839.8,91.7c0,1,0,1.9,0.1,2.8c0.4,14.8,0.8,27.2,1.7,37.4c1.9,21.5,6,33.3,17.1,36.7
|
|
||||||
c3.4,1.1,6.4,1.5,9,1.5c4.4,0,7.6-1.2,9.9-2.6c-2.3,1.4-5.5,2.6-9.9,2.6c-2.6,0-5.6-0.4-9-1.5C841.9,163.6,841,139.4,839.8,91.7
|
|
||||||
M806.6-3.9c-10.8,0-21.9,2-32.8,4.7l23.9,21.6c1,0,2.1-0.1,3.1-0.1c21.4,0,38,9.1,49.3,22.5c12.8,15.3,3.1,56.1,3.9,79
|
|
||||||
c0.9,22.4-5.4,36.8,27.2,40.6c0.4-0.5,0.6-0.8,0.6-0.8s-14.1-0.8-18.4-14.8c-0.8-2.7-1.3-5.8-1.2-9.5c0.1-5.4,2.4-13,5.1-21.9
|
|
||||||
c2.4-7.7,5.1-16.4,7.1-25.7c5.4-25.7,5-55.8-24.9-80.8C836.3,0,821.7-3.9,806.6-3.9 M613.2-59.1c0,4.2,0.2,9.3,0.7,15
|
|
||||||
c2.5,25.9,12.6,64.3,47.8,93.6c20.4,17,39.5,23,56.7,23c13.2,0,25.2-3.5,35.8-8.1c0.5-0.2,1-0.4,1.5-0.7l0,0
|
|
||||||
c-10.9,4.9-23.5,8.7-37.2,8.7c-17.2,0-36.3-5.9-56.7-23C618.9,13.7,613.2-35.6,613.2-59.1 M661.9-65.1c-4.1,5.4-12.5,8.6-21.6,8.6
|
|
||||||
c-1.7,0-3.4-0.1-5.1-0.3c-0.8,25.1,5.1,61.8,29.9,82.4c10.6,8.8,25.2,11.8,40.9,11.8c4.8,0,9.7-0.3,14.7-0.8l35,27.1l-67.1-52.1
|
|
||||||
c-2.3-1.1-4.7-2.6-7-4.5c-24.6-20.5-24.9-46.9-21.9-63.4C660.3-59.7,661.1-62.7,661.9-65.1"/>
|
|
||||||
<path class="st9" d="M800.8,22.4c-1,0-2.1,0-3.1,0.1c0,0-0.1,0-0.1,0l40,36c0.3,0.3,0.6,0.6,0.8,0.9c3.3,4.9,1.6,18.9,1.3,32.3l0,0
|
|
||||||
c1.2,47.7,2.2,71.8,18.9,77c3.4,1.1,6.4,1.5,9,1.5c4.4,0,7.6-1.2,9.9-2.6c1.8-1.1,3-2.3,3.7-3.1c0,0,0,0,0,0
|
|
||||||
c-32.6-3.8-26.3-18.2-27.2-40.6c-0.8-22.9,8.9-63.7-3.9-79C838.8,31.5,822.2,22.4,800.8,22.4 M614.1-73c-0.1,0.2-0.1,0.3-0.1,0.3
|
|
||||||
s-0.7,5.1-0.7,13.6c0,23.6,5.7,72.8,48.5,108.6c20.4,17,39.5,23,56.7,23c13.8,0,26.3-3.8,37.2-8.7l0,0l-35-27.1
|
|
||||||
c-4.9,0.5-9.9,0.8-14.7,0.8c-15.7,0-30.3-3.1-40.9-11.8c-24.8-20.7-30.8-57.4-29.9-82.4c-1.5-0.2-3-0.5-4.5-0.9
|
|
||||||
C620.6-60.3,614.3-66.5,614.1-73"/>
|
|
||||||
<path class="st10" d="M638.2-59.6c-2,0-4.1-0.7-5.9-2.2c-3.7-3.1-4.4-8.2-1.7-11.4c1.4-1.7,3.5-2.5,5.7-2.5c2,0,4.1,0.7,5.9,2.2
|
|
||||||
c3.7,3.1,4.4,8.2,1.7,11.4C642.5-60.5,640.4-59.6,638.2-59.6 M638.2-89c-5.2,0-10.1,1-14.2,2.9c-3.7,1.7-6.7,4.2-8.4,7.1
|
|
||||||
c-1.1,2-1.6,4-1.5,6c0.3,6.5,6.6,12.7,16.5,15.3c1.5,0.4,3,0.7,4.5,0.9c1.7,0.2,3.4,0.3,5.1,0.3c9.1,0,17.5-3.2,21.6-8.6
|
|
||||||
c0.4-0.5,0.7-1,1-1.5c4.7-8.3-2-17.8-15-21.2C644.6-88.6,641.4-89,638.2-89"/>
|
|
||||||
<path class="st11" d="M636.3-75.8c-2.2,0-4.3,0.9-5.7,2.5c-2.7,3.3-2,8.4,1.7,11.4c1.8,1.5,3.9,2.2,5.9,2.2c2.2,0,4.3-0.9,5.7-2.5
|
|
||||||
c2.7-3.3,2-8.4-1.7-11.4C640.5-75.1,638.4-75.8,636.3-75.8"/>
|
|
||||||
<polyline class="st12" points="577.3,-178.5 549.7,-145.7 522.2,-113.1 524.5,-113.4 579.7,-120.8 579.6,-123.3 577.3,-176.6
|
|
||||||
577.3,-178.5 "/>
|
|
||||||
<polyline class="st13" points="563.6,-190 563.5,-190 564.1,-188.9 537.9,-157.6 550.6,-147 577.1,-178.7 563.6,-190 "/>
|
|
||||||
<polyline class="st14" points="563.5,-190 544.2,-166.9 544.4,-166.7 537.2,-158.2 537.9,-157.6 564.1,-188.9 563.5,-190 "/>
|
|
||||||
<polyline class="st15" points="544.2,-166.9 535.1,-156 537,-158.3 537.2,-158.2 544.4,-166.7 544.2,-166.9 "/>
|
|
||||||
<polyline class="st16" points="537.9,-157.6 536.7,-156.1 536.7,-156.1 509.7,-124 508.6,-124.3 522.1,-113 550.6,-147
|
|
||||||
537.9,-157.6 "/>
|
|
||||||
<polyline class="st17" points="537.2,-158.2 536.6,-157.4 537.3,-156.8 536.7,-156.1 536.7,-156.1 537.9,-157.6 537.2,-158.2 "/>
|
|
||||||
<polyline class="st18" points="536.6,-157.4 527.2,-146.2 527,-146.3 508.6,-124.3 508.6,-124.3 509.7,-124 536.7,-156.1
|
|
||||||
537.3,-156.8 536.6,-157.4 "/>
|
|
||||||
<polyline class="st19" points="537,-158.3 535.1,-156 527,-146.3 527.2,-146.2 536.6,-157.4 537.2,-158.2 537,-158.3 "/>
|
|
||||||
<polygon class="st20" points="362.8,-106.5 366.8,-137.1 394.1,-151.2 366.3,-164.3 361.4,-194.7 340.3,-172.4 309.9,-177.1
|
|
||||||
324.6,-150 310.7,-122.6 341,-128.3 "/>
|
|
||||||
<polygon class="st20" points="394.7,-386.8 409.4,-403.2 431.2,-400.3 420.2,-419.4 429.7,-439.2 408.2,-434.6 392.3,-449.7
|
|
||||||
390,-427.9 370.7,-417.4 390.7,-408.5 "/>
|
|
||||||
<polygon class="st20" points="457,20.4 461.6,-14.7 493.1,-30.9 461.1,-46.1 455.4,-81.1 431,-55.3 396,-60.7 413,-29.6 397,2
|
|
||||||
431.8,-4.5 "/>
|
|
||||||
<polygon class="st20" points="634.6,-418.3 636.7,-434.1 650.9,-441.4 636.5,-448.2 633.9,-463.9 623,-452.4 607.2,-454.8
|
|
||||||
614.9,-440.8 607.7,-426.6 623.3,-429.5 "/>
|
|
||||||
<polygon class="st20" points="803.5,-10.6 800.3,-33.9 817.8,-49.6 794.6,-53.9 785,-75.3 773.8,-54.7 750.5,-52.1 766.7,-35.1
|
|
||||||
761.9,-12.1 783.1,-22.3 "/>
|
|
||||||
<polygon class="st20" points="608.2,41.7 610.5,23.5 626.9,15.1 610.3,7.2 607.4,-10.9 594.7,2.5 576.6,-0.4 585.4,15.8
|
|
||||||
577.1,32.1 595.1,28.8 "/>
|
|
||||||
<polygon class="st20" points="267.8,88.3 269.8,72.5 284,65.2 269.6,58.4 267,42.6 256.1,54.2 240.4,51.8 248,65.8 240.8,80
|
|
||||||
256.5,77.1 "/>
|
|
||||||
<polygon class="st20" points="489.7,348 497.5,334.2 513.4,332.8 502.6,321 506.2,305.5 491.7,312.1 478,303.9 479.8,319.7
|
|
||||||
467.8,330.2 483.4,333.4 "/>
|
|
||||||
<polygon class="st20" points="989.4,-441.9 997.3,-455.7 1013.1,-457.1 1002.4,-468.9 1005.9,-484.4 991.4,-477.8 977.8,-486
|
|
||||||
979.6,-470.2 967.5,-459.7 983.2,-456.5 "/>
|
|
||||||
<polygon class="st20" points="934.4,137.9 939.1,126.4 951.4,123.8 941.9,115.7 943.1,103.3 932.5,109.8 921.1,104.8 924,116.9
|
|
||||||
915.7,126.2 928.2,127.1 "/>
|
|
||||||
<polygon class="st20" points="326.5,108.6 324.9,96.3 334.1,87.9 321.8,85.6 316.8,74.3 310.8,85.2 298.5,86.6 307.1,95.6
|
|
||||||
304.5,107.8 315.7,102.4 "/>
|
|
||||||
<polygon class="st20" points="530.6,104.7 532,93.7 541.9,88.7 531.9,83.9 530.1,73 522.5,81 511.6,79.3 516.9,89 511.9,98.9
|
|
||||||
522.7,96.9 "/>
|
|
||||||
<polygon class="st20" points="742.1,-272 745.1,-282.7 755.5,-286.3 746.3,-292.4 746.1,-303.5 737.4,-296.6 726.8,-299.8
|
|
||||||
730.7,-289.5 724.3,-280.4 735.4,-280.9 "/>
|
|
||||||
<polygon class="st20" points="939.7,-208.2 950.1,-211.9 959.1,-205.5 958.7,-216.6 967.5,-223.3 956.9,-226.3 953.4,-236.7
|
|
||||||
947.2,-227.6 936.1,-227.4 943,-218.7 "/>
|
|
||||||
<polygon class="st20" points="825.7,-570.5 829.8,-574.5 835.4,-573.5 832.8,-578.6 835.5,-583.7 829.9,-582.8 825.9,-587
|
|
||||||
825,-581.3 819.8,-578.8 824.9,-576.2 "/>
|
|
||||||
<polygon class="st20" points="862.9,475.8 867,471.8 872.6,472.8 870,467.7 872.7,462.6 867.1,463.5 863.1,459.3 862.2,465
|
|
||||||
857,467.5 862.1,470.1 "/>
|
|
||||||
<polygon class="st20" points="503.3,-554 507.4,-558 513.1,-557 510.5,-562.1 513.2,-567.2 507.5,-566.3 503.6,-570.5
|
|
||||||
502.7,-564.8 497.4,-562.3 502.6,-559.7 "/>
|
|
||||||
<polygon class="st20" points="706.5,302 710.6,297.9 716.3,299 713.6,293.8 716.4,288.7 710.7,289.6 706.7,285.5 705.8,291.1
|
|
||||||
700.6,293.6 705.7,296.2 "/>
|
|
||||||
<polygon class="st20" points="328,488.5 333.8,487.9 337.6,492.2 338.7,486.5 344,484.2 339,481.4 338.4,475.7 334.2,479.6
|
|
||||||
328.6,478.3 331,483.6 "/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 9.2 KiB |
418
dist/app.js
vendored
418
dist/app.js
vendored
|
@ -1,418 +0,0 @@
|
||||||
/**
|
|
||||||
* Misc helper functions
|
|
||||||
*/
|
|
||||||
Object.values = x => Object.keys(x).reduce((y, z) => y.push(x[z]) && y, []);
|
|
||||||
const debounce = (func, wait, immediate) => {
|
|
||||||
let timeout;
|
|
||||||
return function () {
|
|
||||||
let context = this,
|
|
||||||
args = arguments;
|
|
||||||
let later = function () {
|
|
||||||
timeout = null;
|
|
||||||
if (!immediate) func.apply(context, args);
|
|
||||||
};
|
|
||||||
let callNow = immediate && !timeout;
|
|
||||||
clearTimeout(timeout);
|
|
||||||
timeout = setTimeout(later, wait);
|
|
||||||
if (callNow) func.apply(context, args);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
const el = id => $(`[data-template=${ id }]`)[0] || console.error('Unable to render to', id);
|
|
||||||
const clone = obj => JSON.parse(JSON.stringify(obj));
|
|
||||||
const basicDetails = ['level', 'range', 'duration', 'casting_time', 'saving_throw', 'aoe', 'source'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Global store and view holders
|
|
||||||
*/
|
|
||||||
let view = {};
|
|
||||||
let store = {
|
|
||||||
systems: {
|
|
||||||
data: [{
|
|
||||||
friendly: 'Dungeons & Dragons 5e',
|
|
||||||
value: 'dnd5e'
|
|
||||||
}, {
|
|
||||||
friendly: 'HackMaster 4e (WIP)',
|
|
||||||
value: 'hackmaster4e'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See Matching System Friendly and Value
|
|
||||||
*/
|
|
||||||
const matchingSystemProp = (system, requested) => store.systems.data.find(d => d[requested === 'value' ? 'friendly' : 'value'] === system)[requested];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init Local Storage
|
|
||||||
*/
|
|
||||||
const localStorageDefault = (key, val) => {
|
|
||||||
if (localStorage.getItem(key) === null) localStorage.setItem(key, val);
|
|
||||||
};
|
|
||||||
let defaults = {
|
|
||||||
tableSortName: 'name',
|
|
||||||
tableSortRev: false,
|
|
||||||
system: 'dnd5e',
|
|
||||||
classes: [],
|
|
||||||
search: ''
|
|
||||||
};
|
|
||||||
for (let cur in defaults) localStorageDefault(cur, defaults[cur]);
|
|
||||||
|
|
||||||
if (window.location.hash) {
|
|
||||||
let urlSystem = window.location.hash.substr(1).split('/')[0];
|
|
||||||
localStorage.setItem('system', store.systems.data.find(d => d.value === urlSystem).value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Table Sort
|
|
||||||
*/
|
|
||||||
store.tableSort = {
|
|
||||||
data: ['name', 'school', 'level'],
|
|
||||||
current: localStorage.getItem('tableSortName'),
|
|
||||||
rev: localStorage.getItem('tableSortRev') !== 'false'
|
|
||||||
};
|
|
||||||
view.table_sort = Monkberry.render(table_sort, el('table-sort'));
|
|
||||||
view.table_sort.update(store.tableSort);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Systems
|
|
||||||
*/
|
|
||||||
store.systems.current = matchingSystemProp(localStorage.getItem('system'), 'friendly');
|
|
||||||
view.systems_list = Monkberry.render(system_list, el('system-list'));
|
|
||||||
view.systems_list.update(store.systems);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Spell List
|
|
||||||
*/
|
|
||||||
view.spell_list = Monkberry.render(spell_list, el('spell-list'));
|
|
||||||
view.spell_list.update({ data: false });
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Spell Print List
|
|
||||||
*/
|
|
||||||
view.spell_list_print = Monkberry.render(spell_list_print, el('spell-list-print'));
|
|
||||||
view.spell_list_print.update({});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Spell Details
|
|
||||||
*/
|
|
||||||
view.spell_details = Monkberry.render(spell_details, el('spell-details'));
|
|
||||||
view.spell_details.update({ data: {} });
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Class List
|
|
||||||
*/
|
|
||||||
store.classes = {
|
|
||||||
data: [],
|
|
||||||
current: localStorage.getItem('classes') ? localStorage.getItem('classes').split(',') : []
|
|
||||||
};
|
|
||||||
view.class_list = Monkberry.render(class_list, el('class-list'));
|
|
||||||
view.class_list.update({ data: false });
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Search
|
|
||||||
*/
|
|
||||||
store.search = localStorage.getItem('search');
|
|
||||||
view.search_field = Monkberry.render(search_field, el('search-field'));
|
|
||||||
view.search_field.update({ data: store.search });
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Discover Classes
|
|
||||||
*/
|
|
||||||
const discoverClasses = spells => {
|
|
||||||
let classes = [];
|
|
||||||
spells.forEach(spell => {
|
|
||||||
if (!spell.classes) return;
|
|
||||||
spell.classes.forEach(current => {
|
|
||||||
if (!classes.includes(current)) classes.push(current);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return classes.sort((a, b) => a > b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emphasis on important string bits
|
|
||||||
* @param {string} string
|
|
||||||
*/
|
|
||||||
const emphasis = (str = '') => {
|
|
||||||
let keywords = ['constitution', 'con', 'intelligence', 'int', 'wisdom', 'wis', 'strength', 'str', 'dexterity', 'dex', 'charisma', 'cha', 'comeliness', 'com', 'saving throw', 'ability check', 'skill check'];
|
|
||||||
keywords.forEach(word => {
|
|
||||||
let r = new RegExp(` ${ word } `, 'gi');
|
|
||||||
str = str.replace(r, o => ` _${ o.trim() }_ `);
|
|
||||||
});
|
|
||||||
|
|
||||||
str = str.replace(/[\s()<>]+\d+d*\d*(th)*[\s()<>]+/gi, o => ` **${ o.trim() }** `);
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description Prettifier
|
|
||||||
*/
|
|
||||||
const descriptionPrettifier = description => {
|
|
||||||
let md = new Remarkable();
|
|
||||||
description = Array.isArray(description) ? description.join('\n') : description;
|
|
||||||
description = emphasis(description);
|
|
||||||
description = md.render(description);
|
|
||||||
description = description.replace(/\n/g, '<br>');
|
|
||||||
|
|
||||||
return description;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init Spells
|
|
||||||
*/
|
|
||||||
const initSpells = s => s.map((spell, i) => {
|
|
||||||
spell.selected = false;
|
|
||||||
spell.ranking = 0;
|
|
||||||
spell.level = parseInt(spell.level) ? spell.level : 0;
|
|
||||||
return spell;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort Spells
|
|
||||||
*/
|
|
||||||
const sortSpells = (s, sortBy, reverse) => s.sort((a, b) => {
|
|
||||||
let hasFilters = store.classes.current.length || store.search.length;
|
|
||||||
let by = sortBy || hasFilters ? 'ranking' : store.tableSort.current;
|
|
||||||
let rev = reverse || hasFilters ? false : store.tableSort.rev;
|
|
||||||
if (by) {
|
|
||||||
if (a[by] < b[by]) return rev ? 1 : -1;
|
|
||||||
if (a[by] > b[by]) return rev ? -1 : 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search Spells
|
|
||||||
* @param {Array} spells
|
|
||||||
* @param {String} ex 'acid spray'
|
|
||||||
* @return {Array} filtered spells
|
|
||||||
*/
|
|
||||||
const searchSpells = (spells, search) => {
|
|
||||||
// Convert search to array of words
|
|
||||||
search = search.split(' ');
|
|
||||||
// Clone spells so we don't affect the original
|
|
||||||
spells = clone(spells);
|
|
||||||
// Reset rankings
|
|
||||||
spells = spells.map(s => {
|
|
||||||
s.ranking = 0;
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
// Rank spells by # of occurances of search terms
|
|
||||||
spells = spells.map(spell => {
|
|
||||||
search.forEach(term => {
|
|
||||||
let spellText = Object.values(spell).join(' ');
|
|
||||||
let regFind = new RegExp(term, 'gi');
|
|
||||||
spell.ranking += (spellText.match(regFind) || []).length;
|
|
||||||
});
|
|
||||||
return spell;
|
|
||||||
});
|
|
||||||
// Return spells that matched at least something
|
|
||||||
return spells.filter(spell => spell.ranking);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter Spells by Class
|
|
||||||
*/
|
|
||||||
const filterSpellsByClass = (spells, classes) => {
|
|
||||||
// If no classes, default to all classes
|
|
||||||
classes = classes.length ? classes : store.classes.data;
|
|
||||||
// Clone spells so we don't affect the original
|
|
||||||
spells = clone(spells);
|
|
||||||
return spells.filter(spell => {
|
|
||||||
let spellClasses = spell.classes.join(' ');
|
|
||||||
let match = false;
|
|
||||||
classes.forEach(c => {
|
|
||||||
if (spellClasses.indexOf(c) >= 0) {
|
|
||||||
match = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return match;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply Filters
|
|
||||||
* @returns {Array} of spells ranked based on searches and filters
|
|
||||||
*/
|
|
||||||
let applyFilters = () => sortSpells(searchSpells(filterSpellsByClass(store.spells, store.classes.current), store.search));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spell Details Updating
|
|
||||||
*/
|
|
||||||
const spellDetails = name => {
|
|
||||||
if (!name) {
|
|
||||||
view.spell_details.update({ data: {} });
|
|
||||||
$('body').removeClass('details');
|
|
||||||
} else {
|
|
||||||
let data = clone(store.spells.find(spell => name === spell.name));
|
|
||||||
data.description = descriptionPrettifier(data.description);
|
|
||||||
data.details = basicDetails.map(detail => {
|
|
||||||
if (data[detail]) {
|
|
||||||
return {
|
|
||||||
label: detail.replace('_', ' '),
|
|
||||||
value: data[detail]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (data.components && data.components.raw) {
|
|
||||||
data.details.push({ label: 'components', value: data.components.raw });
|
|
||||||
}
|
|
||||||
|
|
||||||
view.spell_details.update({
|
|
||||||
data,
|
|
||||||
url: window.location.href
|
|
||||||
});
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
$('body').addClass('details');
|
|
||||||
let clipboard = new Clipboard('.copy-to-clipboard');
|
|
||||||
clipboard.on('success', e => $('#toast')[0].MaterialSnackbar.showSnackbar({ message: 'Copied link' })).on('error', e => $('#toast')[0].MaterialSnackbar.showSnackbar({ message: 'Sorry! Unable to copy link' }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Print Page
|
|
||||||
*/
|
|
||||||
const renderPrint = () => {
|
|
||||||
let selectedSpells = $('form[data-selected]')
|
|
||||||
// Get array of items in form
|
|
||||||
.serializeArray()
|
|
||||||
// Find spells based on array from form
|
|
||||||
.map(sel => store.spells.find(spell => sel.value === spell.name))
|
|
||||||
// Sort by level then alphabetically
|
|
||||||
.sort((a, b) => {
|
|
||||||
let aName = a.name.toLowerCase();
|
|
||||||
let bName = b.name.toLowerCase();
|
|
||||||
if (a.level > b.level) return 1;
|
|
||||||
if (a.level < b.level) return -1;
|
|
||||||
if (aName > bName) return 1;
|
|
||||||
if (aName < bName) return -1;
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
// Prettify Descriptions
|
|
||||||
.map(spell => {
|
|
||||||
spell = clone(spell);
|
|
||||||
spell.description = descriptionPrettifier(spell.description);
|
|
||||||
spell.details = basicDetails.map(detail => {
|
|
||||||
if (spell[detail]) {
|
|
||||||
return {
|
|
||||||
label: detail.replace('_', ' '),
|
|
||||||
value: spell[detail]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (spell.components && spell.components.raw) {
|
|
||||||
spell.details.push({ label: 'components', value: spell.components.raw });
|
|
||||||
}
|
|
||||||
return spell;
|
|
||||||
});
|
|
||||||
view.spell_list_print.update({ data: selectedSpells });
|
|
||||||
if (selectedSpells.length) {
|
|
||||||
$('[data-action=print] [data-badge]').attr('data-badge', selectedSpells.length);
|
|
||||||
$('[data-action=print]').slideDown('fast');
|
|
||||||
} else {
|
|
||||||
$('[data-action=print]').slideUp('fast');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event Bindings
|
|
||||||
*/
|
|
||||||
$('body')
|
|
||||||
// Listen for header sorts
|
|
||||||
.on('click', '[data-action-sort]', e => {
|
|
||||||
let name = $(e.currentTarget).attr('data-action-sort');
|
|
||||||
let rev = store.tableSort.current === name && !store.tableSort.rev;
|
|
||||||
store.tableSort.current = name;
|
|
||||||
store.tableSort.rev = rev;
|
|
||||||
localStorage.setItem('tableSortName', name);
|
|
||||||
localStorage.setItem('tableSortRev', rev);
|
|
||||||
view.spell_list.update({ data: sortSpells(store.spells) });
|
|
||||||
view.table_sort.update(store.tableSort);
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
})
|
|
||||||
// Listen for checkbox changes to filter spells
|
|
||||||
.on('change', '[data-action-classtoggle]', e => {
|
|
||||||
let name = $(e.currentTarget).attr('data-action-classtoggle');
|
|
||||||
let add = $(e.currentTarget).prop('checked');
|
|
||||||
let index = store.classes.current.indexOf(name);
|
|
||||||
if (index === -1 && add) {
|
|
||||||
store.classes.current.push(name);
|
|
||||||
} else if (!add) store.classes.current.splice(index, 1);
|
|
||||||
store.tableSort.current = store.classes.current.length || store.search.length ? 'ranking' : null;
|
|
||||||
localStorage.setItem('tableSortName', store.tableSort.current);
|
|
||||||
localStorage.setItem('classes', store.classes.current);
|
|
||||||
view.spell_list.update({ data: applyFilters() });
|
|
||||||
view.table_sort.update({ current: store.tableSort.current });
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
})
|
|
||||||
// Listen to search to filter by
|
|
||||||
.on('change keyup cut paste', '[data-action-search]', e => {
|
|
||||||
setTimeout(() => {
|
|
||||||
// Delay for value to change
|
|
||||||
store.search = $(e.currentTarget).val();
|
|
||||||
store.tableSort.current = store.search.length || store.classes.current.length ? 'ranking' : null;
|
|
||||||
store.tableSort.rev = false;
|
|
||||||
localStorage.setItem('search', store.search);
|
|
||||||
localStorage.setItem('tableSortName', store.tableSort.current);
|
|
||||||
localStorage.setItem('tableSortRev', store.tableSort.rev);
|
|
||||||
view.spell_list.update({ data: applyFilters() });
|
|
||||||
view.table_sort.update(store.tableSort);
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
}, 0);
|
|
||||||
})
|
|
||||||
// Listen for click on spells to open details
|
|
||||||
.on('click', '[data-action-details]', e => {
|
|
||||||
let name = $(e.currentTarget).attr('data-action-details');
|
|
||||||
if (name) {
|
|
||||||
window.location.hash = matchingSystemProp(store.systems.current, 'value') + '/' + name;
|
|
||||||
} else {
|
|
||||||
window.location.hash = '';
|
|
||||||
}
|
|
||||||
spellDetails(name);
|
|
||||||
})
|
|
||||||
// Stop propogation if dontprop clicked
|
|
||||||
.on('click', '.dontprop', e => {
|
|
||||||
e.stopPropagation();
|
|
||||||
})
|
|
||||||
// Toggle All
|
|
||||||
.on('change', 'label[for=table-header] input[type=checkbox]', e => {
|
|
||||||
$(e.target).closest('form').find('[name=selected]').each(function () {
|
|
||||||
this.checked = e.target.checked;
|
|
||||||
if (this.checked) $(this).closest('label').addClass('is-checked');else $(this).closest('label').removeClass('is-checked');
|
|
||||||
});
|
|
||||||
renderPrint();
|
|
||||||
}).on('change', 'input[name=selected][type=checkbox]', renderPrint).on('click', '[data-action=print]', e => {
|
|
||||||
window.print();
|
|
||||||
});
|
|
||||||
// Article Scroll with User
|
|
||||||
$('.mdl-layout__content').on('scroll', debounce(() => {
|
|
||||||
let distance = $('.mdl-layout__content')[0].scrollTop;
|
|
||||||
$('[data-template=spell-details]').css('margin-top', distance);
|
|
||||||
}, 10));
|
|
||||||
// System changed
|
|
||||||
$('[data-action=system]').on('change', e => {
|
|
||||||
let system = $(e.currentTarget).val();
|
|
||||||
let systemValue = matchingSystemProp(system, 'value');
|
|
||||||
window.location.hash = '';
|
|
||||||
spellDetails('');
|
|
||||||
store.systems.current = system;
|
|
||||||
localStorage.setItem('system', systemValue);
|
|
||||||
view.spell_list.update({ data: false });
|
|
||||||
view.class_list.update({ data: false });
|
|
||||||
fetchSpells(systemValue);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch Spells
|
|
||||||
*/
|
|
||||||
const fetchSpells = (system = matchingSystemProp(store.systems.current, 'value')) => fetch(`./systems/${ system }.json`).then(response => response.json()).then(spells => initSpells(spells)).then(spells => {
|
|
||||||
store.spells = spells;
|
|
||||||
store.classes.data = discoverClasses(spells);
|
|
||||||
view.spell_list.update({ data: applyFilters() });
|
|
||||||
view.class_list.update(store.classes);
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
if (window.location.hash) spellDetails(window.location.hash.substr(1).split('/')[1]);
|
|
||||||
return spells;
|
|
||||||
}).catch(reason => console.error('Unable to retrieve spells list:', reason));
|
|
||||||
fetchSpells();
|
|
7
dist/clipboard.min.js
vendored
7
dist/clipboard.min.js
vendored
File diff suppressed because one or more lines are too long
3
dist/getmdl-select.min.css
vendored
3
dist/getmdl-select.min.css
vendored
|
@ -1,3 +0,0 @@
|
||||||
.getmdl-select .mdl-icon-toggle__label{float:right;margin-top:-30px;color:rgba(0,0,0,0.4)}.getmdl-select.is-focused .mdl-icon-toggle__label{color:#3f51b5}.getmdl-select .mdl-menu__container{width:100% !important}.getmdl-select .mdl-menu__container .mdl-menu{width:100%}
|
|
||||||
|
|
||||||
/*# sourceMappingURL=getmdl-select.min.css.map */
|
|
2
dist/getmdl-select.min.js
vendored
2
dist/getmdl-select.min.js
vendored
|
@ -1,2 +0,0 @@
|
||||||
"use strict";window.onload=function(){getmdlSelect.init(".getmdl-select"),document.addEventListener("DOMNodeInserted",function(e){componentHandler.upgradeDom()},!1)};var getmdlSelect={addEventListeners:function(e){var t=e.querySelector("input"),n=e.querySelectorAll("li");[].forEach.call(n,function(e){e.onclick=function(){if(t.value=e.textContent,"createEvent"in document){var n=document.createEvent("HTMLEvents");n.initEvent("change",!1,!0),t.dispatchEvent(n)}else t.fireEvent("onchange")}})},init:function(e){var t=document.querySelectorAll(e);[].forEach.call(t,function(e){getmdlSelect.addEventListeners(e)})}};
|
|
||||||
//# sourceMappingURL=getmdl-select.min.js.map
|
|
4
dist/jquery.min.js
vendored
4
dist/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
385
dist/monkberry.js
vendored
385
dist/monkberry.js
vendored
|
@ -1,385 +0,0 @@
|
||||||
/** _ _
|
|
||||||
* /\/\ ___ _ __ | | _| |__ ___ _ __ _ __ _ _
|
|
||||||
* / \ / _ \| '_ \| |/ / '_ \ / _ \ '__| '__| | | |
|
|
||||||
* / /\/\ \ (_) | | | | <| |_) | __/ | | | | |_| |
|
|
||||||
* \/ \/\___/|_| |_|_|\_\_.__/ \___|_| |_| \__, |
|
|
||||||
* |___/
|
|
||||||
*
|
|
||||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
||||||
* Enter -> | | | | | |
|
|
||||||
* + + + +---+ +---+---+ +---+---+ + + +---+ + +---+ + + +
|
|
||||||
* | | | | | | | | | | |
|
|
||||||
* +---+---+---+---+---+ +---+---+---+---+ +---+---+ +---+ + +---+---+ +
|
|
||||||
* | | | | | | | | | |
|
|
||||||
* + + + +---+---+---+ + + +---+---+ + +---+ + +---+---+ + +
|
|
||||||
* | | | | | | | | | | |
|
|
||||||
* + +---+---+ +---+ + + +---+ + +---+---+---+---+---+ + + +---+
|
|
||||||
* | | | | | | | | | | | | | |
|
|
||||||
* + +---+ +---+ +---+---+---+ + + + + + + + +---+---+ + +
|
|
||||||
* | | | | | | | | | | | | |
|
|
||||||
* +---+---+---+ +---+ + + + +---+---+---+ +---+ +---+---+ + + +
|
|
||||||
* | | | | | | | | | | |
|
|
||||||
* + + + +---+---+---+ +---+ + + + +---+ +---+---+ +---+---+ +
|
|
||||||
* | | | | | | | | | | | | |
|
|
||||||
* + + +---+---+ +---+---+---+ +---+ +---+ + + + + + +---+ +
|
|
||||||
* | | | | | | | | | |
|
|
||||||
* +---+---+ + + +---+---+---+---+ +---+ +---+ + +---+---+ + +---+
|
|
||||||
* | | | | | | -> Exit
|
|
||||||
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
||||||
*/
|
|
||||||
(function (document) {
|
|
||||||
/**
|
|
||||||
* Monkberry
|
|
||||||
* @class
|
|
||||||
*/
|
|
||||||
function Monkberry() {
|
|
||||||
this.parent = null;
|
|
||||||
this.nested = [];
|
|
||||||
this.nodes = [];
|
|
||||||
this.filters = null;
|
|
||||||
this.directives = null;
|
|
||||||
this.context = null;
|
|
||||||
this.unbind = null;
|
|
||||||
this.onRender = null;
|
|
||||||
this.onUpdate = null;
|
|
||||||
this.onRemove = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render template and attach it to node.
|
|
||||||
* @param {Monkberry} template
|
|
||||||
* @param {Element} node
|
|
||||||
* @param {Object=} options
|
|
||||||
* @return {Monkberry}
|
|
||||||
*/
|
|
||||||
Monkberry.render = function (template, node, options) {
|
|
||||||
var view;
|
|
||||||
|
|
||||||
if (options && options.noCache) {
|
|
||||||
view = new template();
|
|
||||||
} else {
|
|
||||||
view = template.pool.pop() || new template();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.nodeType == 8) {
|
|
||||||
view.insertBefore(node);
|
|
||||||
} else {
|
|
||||||
view.appendTo(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options) {
|
|
||||||
if (options.parent) {
|
|
||||||
view.parent = options.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.context) {
|
|
||||||
view.context = options.context;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.filters) {
|
|
||||||
view.filters = options.filters;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.directives) {
|
|
||||||
view.directives = options.directives;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view.onRender) {
|
|
||||||
view.onRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
return view;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prerepder template for future usage.
|
|
||||||
* @param {Monkberry} template - Template name.
|
|
||||||
* @param {Number} times - Times of prerender.
|
|
||||||
*/
|
|
||||||
Monkberry.prerender = function (template, times) {
|
|
||||||
while (times--) {
|
|
||||||
template.pool.push(new template());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main loops processor.
|
|
||||||
*/
|
|
||||||
Monkberry.loop = function (parent, node, map, template, array, options) {
|
|
||||||
var i, j, len, keys, transform, arrayLength, childrenSize = map.length;
|
|
||||||
|
|
||||||
// Get array length, and convert object to array if needed.
|
|
||||||
if (Array.isArray(array)) {
|
|
||||||
transform = transformArray;
|
|
||||||
arrayLength = array.length;
|
|
||||||
} else {
|
|
||||||
transform = transformObject;
|
|
||||||
keys = Object.keys(array);
|
|
||||||
arrayLength = keys.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If new array contains less items what before, remove surpluses.
|
|
||||||
len = childrenSize - arrayLength;
|
|
||||||
for (i in map.items) {
|
|
||||||
if (len-- > 0) {
|
|
||||||
map.items[i].remove();
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is already some views, update there loop state.
|
|
||||||
j = 0;
|
|
||||||
for (i in map.items) {
|
|
||||||
map.items[i].__state__ = transform(array, keys, j, options);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If new array contains more items when previous, render new views and append them.
|
|
||||||
for (j = childrenSize, len = arrayLength; j < len; j++) {
|
|
||||||
// Render new view.
|
|
||||||
var view = Monkberry.render(template, node, {parent: parent, context: parent.context, filters: parent.filters, directives: parent.directives});
|
|
||||||
|
|
||||||
// Set view hierarchy.
|
|
||||||
parent.nested.push(view);
|
|
||||||
|
|
||||||
// Remember to remove from children map on view remove.
|
|
||||||
i = map.push(view);
|
|
||||||
view.unbind = (function (i) {
|
|
||||||
return function () {
|
|
||||||
map.remove(i);
|
|
||||||
};
|
|
||||||
})(i);
|
|
||||||
|
|
||||||
// Set view state for later update in onUpdate.
|
|
||||||
view.__state__ = transform(array, keys, j, options);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main if processor.
|
|
||||||
*/
|
|
||||||
Monkberry.cond = function (parent, node, child/*.ref*/, template, test) {
|
|
||||||
if (child.ref) { // If view was already inserted, update or remove it.
|
|
||||||
if (!test) {
|
|
||||||
child.ref.remove();
|
|
||||||
}
|
|
||||||
} else if (test) {
|
|
||||||
// Render new view.
|
|
||||||
var view = Monkberry.render(template, node, {parent: parent, context: parent.context, filters: parent.filters, directives: parent.directives});
|
|
||||||
|
|
||||||
// Set view hierarchy.
|
|
||||||
parent.nested.push(view);
|
|
||||||
|
|
||||||
// Remember to remove child ref on remove of view.
|
|
||||||
child.ref = view;
|
|
||||||
view.unbind = function () {
|
|
||||||
child.ref = null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return test;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main custom tags processor.
|
|
||||||
*/
|
|
||||||
Monkberry.insert = function (parent, node, child/*.ref*/, template, data) {
|
|
||||||
if (child.ref) { // If view was already inserted, update or remove it.
|
|
||||||
child.ref.update(data);
|
|
||||||
} else {
|
|
||||||
// Render new view.
|
|
||||||
var view = Monkberry.render(template, node, {parent: parent, context: parent.context, filters: parent.filters, directives: parent.directives});
|
|
||||||
|
|
||||||
// Set view hierarchy.
|
|
||||||
parent.nested.push(view);
|
|
||||||
|
|
||||||
// Remember to remove child ref on remove of view.
|
|
||||||
child.ref = view;
|
|
||||||
view.unbind = function () {
|
|
||||||
child.ref = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set view data (note what it must be after adding nodes to DOM).
|
|
||||||
view.update(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove view from DOM.
|
|
||||||
*/
|
|
||||||
Monkberry.prototype.remove = function () {
|
|
||||||
// Remove appended nodes.
|
|
||||||
var i = this.nodes.length;
|
|
||||||
while (i--) {
|
|
||||||
this.nodes[i].parentNode.removeChild(this.nodes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove self from parent's children map or child ref.
|
|
||||||
if (this.unbind) {
|
|
||||||
this.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all nested views.
|
|
||||||
i = this.nested.length;
|
|
||||||
while (i--) {
|
|
||||||
this.nested[i].remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove this view from parent's nested views.
|
|
||||||
if (this.parent) {
|
|
||||||
i = this.parent.nested.indexOf(this);
|
|
||||||
this.parent.nested.splice(i, 1);
|
|
||||||
this.parent = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call on remove callback.
|
|
||||||
if (this.onRemove) {
|
|
||||||
this.onRemove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store view in pool for reuse in future.
|
|
||||||
this.constructor.pool.push(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Element} toNode
|
|
||||||
*/
|
|
||||||
Monkberry.prototype.appendTo = function (toNode) {
|
|
||||||
for (var i = 0, len = this.nodes.length; i < len; i++) {
|
|
||||||
toNode.appendChild(this.nodes[i]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Element} toNode
|
|
||||||
*/
|
|
||||||
Monkberry.prototype.insertBefore = function (toNode) {
|
|
||||||
if (toNode.parentNode) {
|
|
||||||
for (var i = 0, len = this.nodes.length; i < len; i++) {
|
|
||||||
toNode.parentNode.insertBefore(this.nodes[i], toNode);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
"Can not insert child view into parent node. " +
|
|
||||||
"You need append your view first and then update."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return rendered node, or DocumentFragment of rendered nodes if more then one root node in template.
|
|
||||||
* @returns {Element|DocumentFragment}
|
|
||||||
*/
|
|
||||||
Monkberry.prototype.createDocument = function () {
|
|
||||||
if (this.nodes.length == 1) {
|
|
||||||
return this.nodes[0];
|
|
||||||
} else {
|
|
||||||
var fragment = document.createDocumentFragment();
|
|
||||||
for (var i = 0, len = this.nodes.length; i < len; i++) {
|
|
||||||
fragment.appendChild(this.nodes[i]);
|
|
||||||
}
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} query
|
|
||||||
* @returns {Element}
|
|
||||||
*/
|
|
||||||
Monkberry.prototype.querySelector = function (query) {
|
|
||||||
for (var i = 0; i < this.nodes.length; i++) {
|
|
||||||
if (this.nodes[i].matches && this.nodes[i].matches(query)) {
|
|
||||||
return this.nodes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.nodes[i].nodeType === 8) {
|
|
||||||
throw new Error('Can not use querySelector with non-element nodes on first level.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.nodes[i].querySelector) {
|
|
||||||
var element = this.nodes[i].querySelector(query);
|
|
||||||
if (element) {
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple Map implementation with length property.
|
|
||||||
*/
|
|
||||||
function Map() {
|
|
||||||
this.items = Object.create(null);
|
|
||||||
this.length = 0;
|
|
||||||
this.next = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map.prototype.push = function (element) {
|
|
||||||
this.items[this.next] = element;
|
|
||||||
this.length += 1;
|
|
||||||
this.next += 1;
|
|
||||||
return this.next - 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
Map.prototype.remove = function (i) {
|
|
||||||
if (i in this.items) {
|
|
||||||
delete this.items[i];
|
|
||||||
this.length -= 1;
|
|
||||||
} else {
|
|
||||||
throw new Error('You are trying to delete not existing element "' + i + '" form map.');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Map.prototype.forEach = function (callback) {
|
|
||||||
for (var i in this.items) {
|
|
||||||
callback(this.items[i]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Monkberry.Map = Map;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Helper function for working with foreach loops data.
|
|
||||||
// Will transform data for "key, value of array" constructions.
|
|
||||||
//
|
|
||||||
|
|
||||||
function transformArray(array, keys, i, options) {
|
|
||||||
if (options) {
|
|
||||||
var t = {__index__: i};
|
|
||||||
t[options.value] = array[i];
|
|
||||||
|
|
||||||
if (options.key) {
|
|
||||||
t[options.key] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
} else {
|
|
||||||
return array[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function transformObject(array, keys, i, options) {
|
|
||||||
if (options) {
|
|
||||||
var t = {__index__: i};
|
|
||||||
t[options.value] = array[keys[i]];
|
|
||||||
|
|
||||||
if (options.key) {
|
|
||||||
t[options.key] = keys[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
} else {
|
|
||||||
return array[keys[i]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof module !== 'undefined') {
|
|
||||||
module.exports = Monkberry;
|
|
||||||
} else {
|
|
||||||
window.Monkberry = Monkberry;
|
|
||||||
}
|
|
||||||
})(window.document);
|
|
4
dist/remarkable.min.js
vendored
4
dist/remarkable.min.js
vendored
File diff suppressed because one or more lines are too long
1241
dist/view.js
vendored
1241
dist/view.js
vendored
File diff suppressed because it is too large
Load diff
1
dist/view.js.map
vendored
1
dist/view.js.map
vendored
|
@ -1 +0,0 @@
|
||||||
{"version":3,"sources":["class-list.monk","search-field.monk","spell-details.monk","spell-list-print.monk","spell-list.monk","system-list.monk","table-sort.monk"],"names":[],"mappings":"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","file":"view.js"}
|
|
116
index.html
116
index.html
|
@ -1,116 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>My Spells</title>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" type="text/css">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
|
||||||
<link rel="stylesheet" href="https://code.getmdl.io/1.1.3/material.teal-pink.min.css" />
|
|
||||||
<link rel="stylesheet" href="./dist/getmdl-select.min.css" />
|
|
||||||
<link rel="stylesheet" href="./assets/app.css" />
|
|
||||||
<link rel="stylesheet" href="./assets/print.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
|
|
||||||
<header class="mdl-layout__header">
|
|
||||||
<div class="mdl-layout__header-row">
|
|
||||||
<div data-template="system-list"></div>
|
|
||||||
<div class="mdl-layout-spacer"></div>
|
|
||||||
<button data-action="print" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-color-text--white">
|
|
||||||
<span class="mdl-badge" data-badge="0">
|
|
||||||
<i class="material-icons">print</i>
|
|
||||||
Print
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<div data-action-details="" role="button" tabindex="0"><i class="material-icons">keyboard_arrow_left</i></div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<aside class="mdl-layout__drawer">
|
|
||||||
<span class="mdl-layout-title mdl-color-text--pink-600">
|
|
||||||
<i class="material-icons">whatshot</i>
|
|
||||||
My Spells
|
|
||||||
</span>
|
|
||||||
<nav class="mdl-navigation">
|
|
||||||
<form>
|
|
||||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
|
||||||
<div data-template="search-field"></div>
|
|
||||||
<label class="mdl-textfield__label">
|
|
||||||
<i class="material-icons">search</i>
|
|
||||||
Search
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form data-template="class-list">
|
|
||||||
</form>
|
|
||||||
</nav>
|
|
||||||
</aside>
|
|
||||||
<main class="mdl-layout__content">
|
|
||||||
<div class="page-content">
|
|
||||||
<form class="mdl-grid" id="selected-spells" data-selected>
|
|
||||||
<table id="spell-list-container" class="mdl-cell mdl-cell--12-col mdl-cell--6-col-desktop mdl-data-table mdl-shadow--2dp">
|
|
||||||
<thead>
|
|
||||||
<tr data-template="table-sort"></tr>
|
|
||||||
</thead>
|
|
||||||
<tbody data-template="spell-list"></tbody>
|
|
||||||
</table>
|
|
||||||
<article data-template="spell-details" class="mdl-cell mdl-cell--12-col mdl-cell--6-col-desktop mdl-color-text--grey-600"></article>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer class="mdl-mini-footer">
|
|
||||||
<div class="mdl-mini-footer__right-section">
|
|
||||||
<div class="mdl-logo hide-phone">My Spells</div>
|
|
||||||
<ul class="mdl-mini-footer__link-list">
|
|
||||||
<li>
|
|
||||||
<a class="hide-phone mdl-navigation__link mdl-color-text--teal-100" href="https://github.com/sharpshark28/my_spells">
|
|
||||||
<i class="material-icons">code</i>
|
|
||||||
Fork Me On Github
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="mdl-navigation__link" href="https://dark12222000.github.io/lootsplit/">
|
|
||||||
<i class="material-icons">local_atm</i>
|
|
||||||
Loot Split
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="mdl-navigation__link" href="http://paulvmoreau.github.io/BeltFedNPCs/">
|
|
||||||
<i class="material-icons">people</i>
|
|
||||||
NPC Generator
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<div id="toast" class="mdl-js-snackbar mdl-snackbar">
|
|
||||||
<div class="mdl-snackbar__text"></div>
|
|
||||||
<button class="mdl-snackbar__action" type="button"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class="printonly">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Spell Name</th>
|
|
||||||
<th>Level</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody data-template="spell-list-print">
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<script src="https://code.getmdl.io/1.1.3/material.min.js"></script>
|
|
||||||
<script src="./dist/getmdl-select.min.js"></script>
|
|
||||||
<script src="./dist/jquery.min.js"></script>
|
|
||||||
<script src="./dist/monkberry.js"></script>
|
|
||||||
<script src="./dist/remarkable.min.js"></script>
|
|
||||||
<script src="./dist/clipboard.min.js"></script>
|
|
||||||
<script src="./dist/view.js"></script>
|
|
||||||
<script src="./dist/app.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
133
ogl.html
133
ogl.html
|
@ -1,133 +0,0 @@
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>Open Game License v0.1 Simplified</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<center><a href="./index.html">OGF Main</a> |
|
|
||||||
<a href="./licenses.html">List of Licenses</a> |
|
|
||||||
Open Game License Text</center>
|
|
||||||
|
|
||||||
<P>THIS LICENSE IS APPROVED FOR GENERAL USE. PERMISSION TO DISTRIBUTE THIS LICENSE
|
|
||||||
IS MADE BY WIZARDS OF THE COAST!</P>
|
|
||||||
|
|
||||||
<P>OPEN GAME LICENSE Version 1.0a</P>
|
|
||||||
|
|
||||||
<P>The following text is the property of Wizards of the Coast, Inc. and is
|
|
||||||
Copyright 2000 Wizards of the Coast, Inc ("Wizards"). All Rights Reserved.</P>
|
|
||||||
|
|
||||||
<P>1. Definitions: (a)"Contributors" means the copyright and/or trademark
|
|
||||||
owners who have contributed Open Game Content; (b)"Derivative Material"
|
|
||||||
means copyrighted material including derivative works and translations
|
|
||||||
(including into other computer languages), potation, modification,
|
|
||||||
correction, addition, extension, upgrade, improvement, compilation,
|
|
||||||
abridgment or other form in which an existing work may be recast,
|
|
||||||
transformed or adapted; (c) "Distribute" means to reproduce, license, rent,
|
|
||||||
lease, sell, broadcast, publicly display, transmit or otherwise distribute;
|
|
||||||
(d)"Open Game Content" means the game mechanic and includes the methods,
|
|
||||||
procedures, processes and routines to the extent such content does not
|
|
||||||
embody the Product Identity and is an enhancement over the prior art and any
|
|
||||||
additional content clearly identified as Open Game Content by the
|
|
||||||
Contributor, and means any work covered by this License, including
|
|
||||||
translations and derivative works under copyright law, but specifically
|
|
||||||
excludes Product Identity. (e) "Product Identity" means product and product
|
|
||||||
line names, logos and identifying marks including trade dress; artifacts;
|
|
||||||
creatures characters; stories, storylines, plots, thematic elements,
|
|
||||||
dialogue, incidents, language, artwork, symbols, designs, depictions,
|
|
||||||
likenesses, formats, poses, concepts, themes and graphic, photographic and
|
|
||||||
other visual or audio representations; names and descriptions of characters,
|
|
||||||
spells, enchantments, personalities, teams, personas, likenesses and special
|
|
||||||
abilities; places, locations, environments, creatures, equipment, magical or
|
|
||||||
supernatural abilities or effects, logos, symbols, or graphic designs; and
|
|
||||||
any other trademark or registered trademark clearly identified as Product
|
|
||||||
identity by the owner of the Product Identity, and which specifically
|
|
||||||
excludes the Open Game Content; (f) "Trademark" means the logos, names,
|
|
||||||
mark, sign, motto, designs that are used by a Contributor to identify itself
|
|
||||||
or its products or the associated products contributed to the Open Game
|
|
||||||
License by the Contributor (g) "Use", "Used" or "Using" means to use,
|
|
||||||
Distribute, copy, edit, format, modify, translate and otherwise create
|
|
||||||
Derivative Material of Open Game Content. (h) "You" or "Your" means the
|
|
||||||
licensee in terms of this agreement.</P>
|
|
||||||
|
|
||||||
<P>2. The License: This License applies to any Open Game Content that contains
|
|
||||||
a notice indicating that the Open Game Content may only be Used under and in
|
|
||||||
terms of this License. You must affix such a notice to any Open Game Content
|
|
||||||
that you Use. No terms may be added to or subtracted from this License
|
|
||||||
except as described by the License itself. No other terms or conditions may
|
|
||||||
be applied to any Open Game Content distributed using this License.</P>
|
|
||||||
|
|
||||||
<P>3.Offer and Acceptance: By Using the Open Game Content You indicate Your
|
|
||||||
acceptance of the terms of this License.</P>
|
|
||||||
|
|
||||||
<P>4. Grant and Consideration: In consideration for agreeing to use this
|
|
||||||
License, the Contributors grant You a perpetual, worldwide, royalty-free,
|
|
||||||
non-exclusive license with the exact terms of this License to Use, the Open
|
|
||||||
Game Content.</P>
|
|
||||||
|
|
||||||
<P>5.Representation of Authority to Contribute: If You are contributing
|
|
||||||
original material as Open Game Content, You represent that Your
|
|
||||||
Contributions are Your original creation and/or You have sufficient rights
|
|
||||||
to grant the rights conveyed by this License.</P>
|
|
||||||
|
|
||||||
<P>6.Notice of License Copyright: You must update the COPYRIGHT NOTICE portion
|
|
||||||
of this License to include the exact text of the COPYRIGHT NOTICE of any
|
|
||||||
Open Game Content You are copying, modifying or distributing, and You must
|
|
||||||
add the title, the copyright date, and the copyright holder's name to the
|
|
||||||
COPYRIGHT NOTICE of any original Open Game Content you Distribute.</P>
|
|
||||||
|
|
||||||
<P>7. Use of Product Identity: You agree not to Use any Product Identity,
|
|
||||||
including as an indication as to compatibility, except as expressly licensed
|
|
||||||
in another, independent Agreement with the owner of each element of that
|
|
||||||
Product Identity. You agree not to indicate compatibility or
|
|
||||||
co-adaptability with any Trademark or Registered Trademark in conjunction with a work containing
|
|
||||||
Open Game Content except as expressly licensed in another, independent
|
|
||||||
Agreement with the owner of such Trademark or Registered Trademark. The use of any Product Identity
|
|
||||||
in Open Game Content does not constitute a challenge to the ownership of
|
|
||||||
that Product Identity. The owner of any Product Identity used in Open Game
|
|
||||||
Content shall retain all rights, title and interest in and to that Product
|
|
||||||
Identity.</P>
|
|
||||||
|
|
||||||
<P>8. Identification: If you distribute Open Game Content You must clearly
|
|
||||||
indicate which portions of the work that you are distributing are Open Game
|
|
||||||
Content.</P>
|
|
||||||
|
|
||||||
<P>9. Updating the License: Wizards or its designated Agents may publish
|
|
||||||
updated versions of this License. You may use any authorized version of
|
|
||||||
this License to copy, modify and distribute any Open Game Content originally
|
|
||||||
distributed under any version of this License.</P>
|
|
||||||
|
|
||||||
<P>10 Copy of this License: You MUST include a copy of this License with every
|
|
||||||
copy of the Open Game Content You Distribute.</P>
|
|
||||||
|
|
||||||
<P>11. Use of Contributor Credits: You may not market or advertise the Open
|
|
||||||
Game Content using the name of any Contributor unless You have written
|
|
||||||
permission from the Contributor to do so.</P>
|
|
||||||
|
|
||||||
<P>12 Inability to Comply: If it is impossible for You to comply with any of
|
|
||||||
the terms of this License with respect to some or all of the Open Game
|
|
||||||
Content due to statute, judicial order, or governmental regulation then You
|
|
||||||
may not Use any Open Game Material so affected.</P>
|
|
||||||
|
|
||||||
<P>13 Termination: This License will terminate automatically if You fail to
|
|
||||||
comply with all terms herein and fail to cure such breach within 30 days of
|
|
||||||
becoming aware of the breach. All sublicenses shall survive the termination
|
|
||||||
of this License.</P>
|
|
||||||
|
|
||||||
<P>14 Reformation: If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent necessary
|
|
||||||
to make it enforceable.</P>
|
|
||||||
|
|
||||||
<P>15 COPYRIGHT NOTICE<br>
|
|
||||||
Open Game License v 1.0 Copyright 2000, Wizards of the Coast, Inc.</P>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<center><a href="./index.html">OGF Main</a></Center>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
31
package.json
31
package.json
|
@ -1,31 +0,0 @@
|
||||||
{
|
|
||||||
"name": "my_spells_5e",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "5e Spells by Class",
|
|
||||||
"main": "",
|
|
||||||
"watch": {
|
|
||||||
"views": "views/*.monk"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"postinstall": "mkdir -p dist && cp node_modules/clipboard/dist/clipboard.min.js dist && cp node_modules/jquery/dist/jquery.min.js dist && cp node_modules/monkberry/monkberry.js dist && cp node_modules/remarkable/dist/remarkable.min.js dist && cp node_modules/getmdl-select/getmdl-select.min.css dist && cp node_modules/getmdl-select/getmdl-select.min.js dist",
|
|
||||||
"views": "monkberry src/views/*.monk --source-map --output dist/view.js",
|
|
||||||
"js": "babel src/app.js --out-file dist/app.js",
|
|
||||||
"develop": "nodemon --watch src -e monk,js --exec 'npm run views && npm run js'"
|
|
||||||
},
|
|
||||||
"author": "Joe Wroten <sharpshark28@gmail.com>",
|
|
||||||
"license": "ISC",
|
|
||||||
"devDependencies": {
|
|
||||||
"babel-cli": "^6.11.4",
|
|
||||||
"babel-plugin-transform-runtime": "^6.12.0",
|
|
||||||
"babel-preset-es2017": "^1.6.1",
|
|
||||||
"nodemon": "^1.10.0",
|
|
||||||
"npm-watch": "^0.1.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"clipboard": "^1.5.12",
|
|
||||||
"getmdl-select": "^1.0.4",
|
|
||||||
"jquery": "^3.1.0",
|
|
||||||
"monkberry": "^4.0.7",
|
|
||||||
"remarkable": "^1.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
BIN
src/.DS_Store
vendored
BIN
src/.DS_Store
vendored
Binary file not shown.
435
src/app.js
435
src/app.js
|
@ -1,435 +0,0 @@
|
||||||
/**
|
|
||||||
* Misc helper functions
|
|
||||||
*/
|
|
||||||
Object.values = x =>
|
|
||||||
Object.keys(x).reduce((y, z) =>
|
|
||||||
y.push(x[z]) && y, []);
|
|
||||||
const debounce = (func, wait, immediate) => {
|
|
||||||
let timeout;
|
|
||||||
return function() {
|
|
||||||
let context = this, args = arguments;
|
|
||||||
let later = function() {
|
|
||||||
timeout = null;
|
|
||||||
if (!immediate) func.apply(context, args);
|
|
||||||
};
|
|
||||||
let callNow = immediate && !timeout;
|
|
||||||
clearTimeout(timeout);
|
|
||||||
timeout = setTimeout(later, wait);
|
|
||||||
if (callNow) func.apply(context, args);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
const el = id => $(`[data-template=${id}]`)[0] || console.error('Unable to render to', id);
|
|
||||||
const clone = obj => JSON.parse(JSON.stringify(obj));
|
|
||||||
const basicDetails = ['level', 'range', 'duration', 'casting_time', 'saving_throw', 'aoe', 'source'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Global store and view holders
|
|
||||||
*/
|
|
||||||
let view = {};
|
|
||||||
let store = {
|
|
||||||
systems: {
|
|
||||||
data: [{
|
|
||||||
friendly: 'Dungeons & Dragons 5e',
|
|
||||||
value: 'dnd5e'
|
|
||||||
}, {
|
|
||||||
friendly: 'HackMaster 4e (WIP)',
|
|
||||||
value: 'hackmaster4e'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See Matching System Friendly and Value
|
|
||||||
*/
|
|
||||||
const matchingSystemProp = (system, requested) => store.systems.data.find(d => d[requested === 'value' ? 'friendly' : 'value'] === system)[requested];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init Local Storage
|
|
||||||
*/
|
|
||||||
const localStorageDefault = (key, val) => {
|
|
||||||
if (localStorage.getItem(key) === null) localStorage.setItem(key, val);
|
|
||||||
};
|
|
||||||
let defaults = {
|
|
||||||
tableSortName: 'name',
|
|
||||||
tableSortRev: false,
|
|
||||||
system: 'dnd5e',
|
|
||||||
classes: [],
|
|
||||||
search: ''
|
|
||||||
};
|
|
||||||
for (let cur in defaults) localStorageDefault(cur, defaults[cur]);
|
|
||||||
|
|
||||||
if (window.location.hash) {
|
|
||||||
let urlSystem = window.location.hash.substr(1).split('/')[0];
|
|
||||||
localStorage.setItem('system', store.systems.data.find(d => d.value === urlSystem).value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Table Sort
|
|
||||||
*/
|
|
||||||
store.tableSort = {
|
|
||||||
data: ['name', 'school', 'level'],
|
|
||||||
current: localStorage.getItem('tableSortName'),
|
|
||||||
rev: localStorage.getItem('tableSortRev') !== 'false'
|
|
||||||
};
|
|
||||||
view.table_sort = Monkberry.render(table_sort, el('table-sort'));
|
|
||||||
view.table_sort.update(store.tableSort);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Systems
|
|
||||||
*/
|
|
||||||
store.systems.current = matchingSystemProp(localStorage.getItem('system'), 'friendly');
|
|
||||||
view.systems_list = Monkberry.render(system_list, el('system-list'));
|
|
||||||
view.systems_list.update(store.systems);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Spell List
|
|
||||||
*/
|
|
||||||
view.spell_list = Monkberry.render(spell_list, el('spell-list'));
|
|
||||||
view.spell_list.update({data: false});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Spell Print List
|
|
||||||
*/
|
|
||||||
view.spell_list_print = Monkberry.render(spell_list_print, el('spell-list-print'));
|
|
||||||
view.spell_list_print.update({});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Spell Details
|
|
||||||
*/
|
|
||||||
view.spell_details = Monkberry.render(spell_details, el('spell-details'));
|
|
||||||
view.spell_details.update({data: {}});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Class List
|
|
||||||
*/
|
|
||||||
store.classes = {
|
|
||||||
data: [],
|
|
||||||
current: localStorage.getItem('classes') ? localStorage.getItem('classes').split(',') : []
|
|
||||||
};
|
|
||||||
view.class_list = Monkberry.render(class_list, el('class-list'));
|
|
||||||
view.class_list.update({data: false});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Search
|
|
||||||
*/
|
|
||||||
store.search = localStorage.getItem('search');
|
|
||||||
view.search_field = Monkberry.render(search_field, el('search-field'));
|
|
||||||
view.search_field.update({data: store.search});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Discover Classes
|
|
||||||
*/
|
|
||||||
const discoverClasses = spells => {
|
|
||||||
let classes = [];
|
|
||||||
spells.forEach(spell => {
|
|
||||||
if (!spell.classes) return;
|
|
||||||
spell.classes.forEach(current => {
|
|
||||||
if (!classes.includes(current)) classes.push(current);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return classes.sort((a, b) => a > b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emphasis on important string bits
|
|
||||||
* @param {string} string
|
|
||||||
*/
|
|
||||||
const emphasis = (str = '') => {
|
|
||||||
let keywords = ['constitution', 'con', 'intelligence', 'int', 'wisdom', 'wis', 'strength', 'str', 'dexterity', 'dex', 'charisma', 'cha', 'comeliness', 'com', 'saving throw', 'ability check', 'skill check'];
|
|
||||||
keywords.forEach(word => {
|
|
||||||
let r = new RegExp(` ${word} `, 'gi');
|
|
||||||
str = str.replace(r, o => ` _${o.trim()}_ `);
|
|
||||||
});
|
|
||||||
|
|
||||||
str = str.replace(/[\s()<>]+\d+d*\d*(th)*[\s()<>]+/gi, o => ` **${o.trim()}** `);
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description Prettifier
|
|
||||||
*/
|
|
||||||
const descriptionPrettifier = description => {
|
|
||||||
let md = new Remarkable();
|
|
||||||
description = Array.isArray(description) ? description.join('\n') : description;
|
|
||||||
description = emphasis(description);
|
|
||||||
description = md.render(description);
|
|
||||||
description = description.replace(/\n/g, '<br>');
|
|
||||||
|
|
||||||
return description;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init Spells
|
|
||||||
*/
|
|
||||||
const initSpells = s => s.map((spell, i) => {
|
|
||||||
spell.selected = false;
|
|
||||||
spell.ranking = 0;
|
|
||||||
spell.level = parseInt(spell.level) ? spell.level : 0;
|
|
||||||
return spell;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort Spells
|
|
||||||
*/
|
|
||||||
const sortSpells = (s, sortBy, reverse) => s.sort((a, b) => {
|
|
||||||
let hasFilters = store.classes.current.length || store.search.length;
|
|
||||||
let by = sortBy || hasFilters ? 'ranking' : store.tableSort.current;
|
|
||||||
let rev = reverse || hasFilters ? false : store.tableSort.rev;
|
|
||||||
if (by) {
|
|
||||||
if (a[by] < b[by]) return rev ? 1 : -1;
|
|
||||||
if (a[by] > b[by]) return rev ? -1 : 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search Spells
|
|
||||||
* @param {Array} spells
|
|
||||||
* @param {String} ex 'acid spray'
|
|
||||||
* @return {Array} filtered spells
|
|
||||||
*/
|
|
||||||
const searchSpells = (spells, search) => {
|
|
||||||
// Convert search to array of words
|
|
||||||
search = search.split(' ');
|
|
||||||
// Clone spells so we don't affect the original
|
|
||||||
spells = clone(spells);
|
|
||||||
// Reset rankings
|
|
||||||
spells = spells.map(s => {
|
|
||||||
s.ranking = 0;
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
// Rank spells by # of occurances of search terms
|
|
||||||
spells = spells.map(spell => {
|
|
||||||
search.forEach(term => {
|
|
||||||
let spellText = Object.values(spell).join(' ');
|
|
||||||
let regFind = new RegExp(term, 'gi');
|
|
||||||
spell.ranking += (spellText.match(regFind) || []).length;
|
|
||||||
});
|
|
||||||
return spell;
|
|
||||||
});
|
|
||||||
// Return spells that matched at least something
|
|
||||||
return spells.filter(spell => spell.ranking);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter Spells by Class
|
|
||||||
*/
|
|
||||||
const filterSpellsByClass = (spells, classes) => {
|
|
||||||
// If no classes, default to all classes
|
|
||||||
classes = classes.length ? classes : store.classes.data;
|
|
||||||
// Clone spells so we don't affect the original
|
|
||||||
spells = clone(spells);
|
|
||||||
return spells.filter(spell => {
|
|
||||||
let spellClasses = spell.classes.join(' ');
|
|
||||||
let match = false;
|
|
||||||
classes.forEach(c => {
|
|
||||||
if (spellClasses.indexOf(c) >= 0) {
|
|
||||||
match = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return match;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply Filters
|
|
||||||
* @returns {Array} of spells ranked based on searches and filters
|
|
||||||
*/
|
|
||||||
let applyFilters = () => sortSpells(
|
|
||||||
searchSpells(
|
|
||||||
filterSpellsByClass(
|
|
||||||
store.spells,
|
|
||||||
store.classes.current
|
|
||||||
),
|
|
||||||
store.search
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spell Details Updating
|
|
||||||
*/
|
|
||||||
const spellDetails = name => {
|
|
||||||
if (!name) {
|
|
||||||
view.spell_details.update({data: {}});
|
|
||||||
$('body').removeClass('details');
|
|
||||||
} else {
|
|
||||||
let data = clone(store.spells.find(spell => name === spell.name));
|
|
||||||
data.description = descriptionPrettifier(data.description);
|
|
||||||
data.details = basicDetails.map(detail => {
|
|
||||||
if (data[detail]) {
|
|
||||||
return {
|
|
||||||
label: detail.replace('_', ' '),
|
|
||||||
value: data[detail]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (data.components && data.components.raw) {
|
|
||||||
data.details.push({label: 'components', value: data.components.raw});
|
|
||||||
}
|
|
||||||
|
|
||||||
view.spell_details.update({
|
|
||||||
data,
|
|
||||||
url: window.location.href
|
|
||||||
});
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
$('body').addClass('details');
|
|
||||||
let clipboard = new Clipboard('.copy-to-clipboard');
|
|
||||||
clipboard
|
|
||||||
.on('success', e => $('#toast')[0].MaterialSnackbar.showSnackbar({message: 'Copied link'}))
|
|
||||||
.on('error', e => $('#toast')[0].MaterialSnackbar.showSnackbar({message: 'Sorry! Unable to copy link'}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render Print Page
|
|
||||||
*/
|
|
||||||
const renderPrint = () => {
|
|
||||||
let selectedSpells = $('form[data-selected]')
|
|
||||||
// Get array of items in form
|
|
||||||
.serializeArray()
|
|
||||||
// Find spells based on array from form
|
|
||||||
.map(sel => store.spells.find(spell => sel.value === spell.name))
|
|
||||||
// Sort by level then alphabetically
|
|
||||||
.sort((a, b) => {
|
|
||||||
let aName = a.name.toLowerCase();
|
|
||||||
let bName = b.name.toLowerCase();
|
|
||||||
if (a.level > b.level) return 1;
|
|
||||||
if (a.level < b.level) return -1;
|
|
||||||
if (aName > bName) return 1;
|
|
||||||
if (aName < bName) return -1;
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
// Prettify Descriptions
|
|
||||||
.map(spell => {
|
|
||||||
spell = clone(spell);
|
|
||||||
spell.description = descriptionPrettifier(spell.description);
|
|
||||||
spell.details = basicDetails.map(detail => {
|
|
||||||
if (spell[detail]) {
|
|
||||||
return {
|
|
||||||
label: detail.replace('_', ' '),
|
|
||||||
value: spell[detail]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (spell.components && spell.components.raw) {
|
|
||||||
spell.details.push({label: 'components', value: spell.components.raw});
|
|
||||||
}
|
|
||||||
return spell;
|
|
||||||
});
|
|
||||||
view.spell_list_print.update({data: selectedSpells});
|
|
||||||
if (selectedSpells.length) {
|
|
||||||
$('[data-action=print] [data-badge]').attr('data-badge', selectedSpells.length);
|
|
||||||
$('[data-action=print]').slideDown('fast');
|
|
||||||
} else {
|
|
||||||
$('[data-action=print]').slideUp('fast');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event Bindings
|
|
||||||
*/
|
|
||||||
$('body')
|
|
||||||
// Listen for header sorts
|
|
||||||
.on('click', '[data-action-sort]', e => {
|
|
||||||
let name = $(e.currentTarget).attr('data-action-sort');
|
|
||||||
let rev = store.tableSort.current === name && !store.tableSort.rev;
|
|
||||||
store.tableSort.current = name;
|
|
||||||
store.tableSort.rev = rev;
|
|
||||||
localStorage.setItem('tableSortName', name);
|
|
||||||
localStorage.setItem('tableSortRev', rev);
|
|
||||||
view.spell_list.update({data: sortSpells(store.spells)});
|
|
||||||
view.table_sort.update(store.tableSort);
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
})
|
|
||||||
// Listen for checkbox changes to filter spells
|
|
||||||
.on('change', '[data-action-classtoggle]', e => {
|
|
||||||
let name = $(e.currentTarget).attr('data-action-classtoggle');
|
|
||||||
let add = $(e.currentTarget).prop('checked');
|
|
||||||
let index = store.classes.current.indexOf(name);
|
|
||||||
if (index === -1 && add) {
|
|
||||||
store.classes.current.push(name);
|
|
||||||
} else if (!add) store.classes.current.splice(index, 1);
|
|
||||||
store.tableSort.current = store.classes.current.length || store.search.length ? 'ranking' : null;
|
|
||||||
localStorage.setItem('tableSortName', store.tableSort.current);
|
|
||||||
localStorage.setItem('classes', store.classes.current);
|
|
||||||
view.spell_list.update({data: applyFilters()});
|
|
||||||
view.table_sort.update({current: store.tableSort.current});
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
})
|
|
||||||
// Listen to search to filter by
|
|
||||||
.on('change keyup cut paste', '[data-action-search]', e => {
|
|
||||||
setTimeout(() => { // Delay for value to change
|
|
||||||
store.search = $(e.currentTarget).val();
|
|
||||||
store.tableSort.current = store.search.length || store.classes.current.length ? 'ranking' : null;
|
|
||||||
store.tableSort.rev = false;
|
|
||||||
localStorage.setItem('search', store.search);
|
|
||||||
localStorage.setItem('tableSortName', store.tableSort.current);
|
|
||||||
localStorage.setItem('tableSortRev', store.tableSort.rev);
|
|
||||||
view.spell_list.update({data: applyFilters()});
|
|
||||||
view.table_sort.update(store.tableSort);
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
}, 0);
|
|
||||||
})
|
|
||||||
// Listen for click on spells to open details
|
|
||||||
.on('click', '[data-action-details]', e => {
|
|
||||||
let name = $(e.currentTarget).attr('data-action-details');
|
|
||||||
if (name) {
|
|
||||||
window.location.hash = matchingSystemProp(store.systems.current, 'value') + '/' + name;
|
|
||||||
} else {
|
|
||||||
window.location.hash = '';
|
|
||||||
}
|
|
||||||
spellDetails(name);
|
|
||||||
})
|
|
||||||
// Stop propogation if dontprop clicked
|
|
||||||
.on('click', '.dontprop', e => {
|
|
||||||
e.stopPropagation();
|
|
||||||
})
|
|
||||||
// Toggle All
|
|
||||||
.on('change', 'label[for=table-header] input[type=checkbox]', e => {
|
|
||||||
$(e.target).closest('form').find('[name=selected]').each(function() {
|
|
||||||
this.checked = e.target.checked;
|
|
||||||
if(this.checked) $(this).closest('label').addClass('is-checked');
|
|
||||||
else $(this).closest('label').removeClass('is-checked');
|
|
||||||
});
|
|
||||||
renderPrint();
|
|
||||||
})
|
|
||||||
.on('change', 'input[name=selected][type=checkbox]', renderPrint)
|
|
||||||
.on('click', '[data-action=print]', e => {
|
|
||||||
window.print();
|
|
||||||
});
|
|
||||||
// Article Scroll with User
|
|
||||||
$('.mdl-layout__content').on('scroll', debounce(() => {
|
|
||||||
let distance = $('.mdl-layout__content')[0].scrollTop;
|
|
||||||
$('[data-template=spell-details]').css('margin-top', distance);
|
|
||||||
}, 10));
|
|
||||||
// System changed
|
|
||||||
$('[data-action=system]').on('change', e => {
|
|
||||||
let system = $(e.currentTarget).val();
|
|
||||||
let systemValue = matchingSystemProp(system, 'value');
|
|
||||||
window.location.hash = '';
|
|
||||||
spellDetails('');
|
|
||||||
store.systems.current = system;
|
|
||||||
localStorage.setItem('system', systemValue);
|
|
||||||
view.spell_list.update({data: false});
|
|
||||||
view.class_list.update({data: false});
|
|
||||||
fetchSpells(systemValue);
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch Spells
|
|
||||||
*/
|
|
||||||
const fetchSpells = (system = matchingSystemProp(store.systems.current, 'value')) => fetch(`./systems/${system}.json`)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(spells => initSpells(spells))
|
|
||||||
.then(spells => {
|
|
||||||
store.spells = spells;
|
|
||||||
store.classes.data = discoverClasses(spells);
|
|
||||||
view.spell_list.update({data: applyFilters()});
|
|
||||||
view.class_list.update(store.classes);
|
|
||||||
componentHandler.upgradeDom();
|
|
||||||
if (window.location.hash) spellDetails(window.location.hash.substr(1).split('/')[1]);
|
|
||||||
return spells;
|
|
||||||
})
|
|
||||||
.catch(reason => console.error('Unable to retrieve spells list:', reason));
|
|
||||||
fetchSpells();
|
|
|
@ -1,19 +0,0 @@
|
||||||
{% if data %}
|
|
||||||
{% for cur of data %}
|
|
||||||
<label class="mdl-navigation__link">
|
|
||||||
<div class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
|
||||||
{% if current.includes(cur) %}
|
|
||||||
<input checked data-action-classtoggle="{{ cur }}" name="class" type="checkbox" class="mdl-switch__input" />
|
|
||||||
{% else %}
|
|
||||||
<input data-action-classtoggle="{{ cur }}" name="class" type="checkbox" class="mdl-switch__input" />
|
|
||||||
{% endif %}
|
|
||||||
<span class="mdl-switch__label">
|
|
||||||
{{ cur }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
<input value="{{ data }}" class="mdl-textfield__input" data-action-search type="text" id="fixed-header-drawer-exp" />
|
|
|
@ -1,27 +0,0 @@
|
||||||
{% if data.name %}
|
|
||||||
<button data-action-details="" class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab">
|
|
||||||
<i class="material-icons">close</i>
|
|
||||||
</button>
|
|
||||||
<h5 class="mdl-typography--display-1 mdl-color-text--teal-600">{{ data.name }}</h5>
|
|
||||||
<ul id="details">
|
|
||||||
{% for detail of data.details %}
|
|
||||||
<li>
|
|
||||||
<strong>{{ detail.label }}</strong> {{ detail.value }}
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
<p id="description">{% unsafe data.description %}</p>
|
|
||||||
|
|
||||||
<div class="mdl-textfield mdl-js-textfield" id="copy">
|
|
||||||
<label class="mdl-button mdl-js-button mdl-button--icon copy-to-clipboard" for="share-url" data-clipboard-target="#share-url">
|
|
||||||
<i class="material-icons">content_copy</i>
|
|
||||||
</label>
|
|
||||||
<input readonly class="mdl-textfield__input" type="text" id="share-url" value="{{ url }}">
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div id="empty">
|
|
||||||
<h6 class="mdl-typography--title">
|
|
||||||
Choose a Spell
|
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
|
@ -1,23 +0,0 @@
|
||||||
{% for spell of data %}
|
|
||||||
<tr>
|
|
||||||
<td class="spell-name">
|
|
||||||
<strong>
|
|
||||||
{{ spell.name }}
|
|
||||||
</strong>
|
|
||||||
</td>
|
|
||||||
<td class="spell-level">
|
|
||||||
{{ spell.level }}
|
|
||||||
</td>
|
|
||||||
<td class="spell-description">
|
|
||||||
<ul id="details">
|
|
||||||
{% for detail of spell.details %}
|
|
||||||
<li>
|
|
||||||
<strong>{{ detail.label }}</strong> {{ detail.value }}
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{% unsafe spell.description %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
|
@ -1,40 +0,0 @@
|
||||||
{% if data.length %}
|
|
||||||
{% for spell of data %}
|
|
||||||
{% if spell.name %}
|
|
||||||
<tr data-action-details="{{ spell.name }}">
|
|
||||||
<td class="hide-phone">
|
|
||||||
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect mdl-data-table__select dontprop">
|
|
||||||
<input type="checkbox" name="selected" value="{{ spell.name }}" class="mdl-checkbox__input dontprop" />
|
|
||||||
</label>
|
|
||||||
</td>
|
|
||||||
<td class="spell-name mdl-data-table__cell--non-numeric">
|
|
||||||
<strong>
|
|
||||||
{{ spell.name }}
|
|
||||||
</strong>
|
|
||||||
</td>
|
|
||||||
<td class="spell-school mdl-data-table__cell--non-numeric">
|
|
||||||
{{ spell.school }}
|
|
||||||
</td>
|
|
||||||
<td class="spell-level">
|
|
||||||
{{ spell.level }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
<tr class="do-nothing">
|
|
||||||
<td colspan="4">
|
|
||||||
{% if data %}
|
|
||||||
<div class="text-center">
|
|
||||||
<i class="material-icons mdl-list__item-icon mdl-color-text--orange-600">
|
|
||||||
warning
|
|
||||||
</i>
|
|
||||||
<h5>No Results</h5>
|
|
||||||
<h6>Try refining your filters in the sidebar.</h6>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{% if data %}
|
|
||||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label getmdl-select">
|
|
||||||
<input class="mdl-textfield__input" data-action="system" value="{{ current }}" type="text" id="system" readonly tabIndex="-1"/>
|
|
||||||
<label class="mdl-textfield__label mdl-color-text--white" for="system">System</label>
|
|
||||||
<ul class="mdl-menu mdl-menu--bottom-left mdl-js-menu" for="system">
|
|
||||||
{% for system of data %}
|
|
||||||
<li class="mdl-menu__item">{{ system.friendly }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
|
@ -1,28 +0,0 @@
|
||||||
<th class="hide-phone">
|
|
||||||
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect mdl-data-table__select" for="table-header">
|
|
||||||
<input type="checkbox" id="table-header" class="mdl-checkbox__input" />
|
|
||||||
</label>
|
|
||||||
</th>
|
|
||||||
{% for name of data %}
|
|
||||||
<th data-action-sort="{{ name }}" class="mdl-data-table__cell--non-numeric {{ current === 'ranking' ? 'mdl-color-text--grey-200 do-nothing' : '' }}">
|
|
||||||
<i class="material-icons mdl-list__item-icon">
|
|
||||||
{% if name === 'level' %}
|
|
||||||
exposure
|
|
||||||
{% endif %}
|
|
||||||
{% if name === 'name' %}
|
|
||||||
flash_on
|
|
||||||
{% endif %}
|
|
||||||
{% if name === 'school' %}
|
|
||||||
school
|
|
||||||
{% endif %}
|
|
||||||
</i>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
{{ name }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<i class="material-icons mdl-color-text--teal-600 mdl-list__item-icon {{ name === current ? 'mdl-color-text--teal-600' : 'mdl-color-text--grey-300' }}">
|
|
||||||
{{ rev ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}
|
|
||||||
</i>
|
|
||||||
</th>
|
|
||||||
{% endfor %}
|
|
10890
systems/dnd5e.json
10890
systems/dnd5e.json
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue