├── .gitignore ├── .hg_archival.txt ├── .prettierrc ├── README.md ├── build ├── dist │ ├── definition.d.ts │ ├── definition.js │ ├── definition.js.map │ ├── link.d.ts │ ├── link.js │ ├── link.js.map │ ├── node.d.ts │ ├── node.js │ ├── node.js.map │ ├── story-plan-organizer.d.ts │ ├── story-plan-organizer.js │ ├── story-plan-organizer.js.map │ ├── uuid.d.ts │ ├── uuid.js │ └── uuid.js.map └── tsconfig.tsbuildinfo ├── data ├── sample1.json └── sample2.json ├── eslint.config.js ├── images ├── splash1.png └── splash2.png ├── img ├── asc.gif ├── bg.gif ├── conv30.png ├── conv40.png ├── conv50.png ├── desc.gif ├── glyphicons-halflings-white.png ├── glyphicons-halflings.png ├── heart30.png ├── heart40.png ├── heart50.png ├── lastfm.gif ├── m1.png ├── m2.png ├── m3.png ├── m4.png ├── m5.png ├── people35.png ├── people45.png ├── people55.png ├── pin.png └── songkick.png ├── index.html ├── js ├── eventslist.js ├── eventsmap.js ├── filter.js ├── lastfm.js ├── songkick.js ├── status.js ├── ui.js └── util.js ├── lib ├── bootstrap-alert.js ├── bootstrap-dropdown.js ├── bootstrap-modal.js ├── bootstrap-typeahead.js ├── bootstrap.min.css ├── bootstrap.min.js ├── jquery-3.1.1.min.js ├── jquery-ui │ ├── css │ │ └── blitzer │ │ │ ├── images │ │ │ ├── ui-bg_diagonals-thick_75_f3d8d8_40x40.png │ │ │ ├── ui-bg_dots-small_65_a6a6a6_2x2.png │ │ │ ├── ui-bg_flat_0_333333_40x100.png │ │ │ ├── ui-bg_flat_65_ffffff_40x100.png │ │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ │ ├── ui-bg_glass_55_fbf8ee_1x400.png │ │ │ ├── ui-bg_highlight-hard_100_eeeeee_1x100.png │ │ │ ├── ui-bg_highlight-hard_100_f6f6f6_1x100.png │ │ │ ├── ui-bg_highlight-soft_15_cc0000_1x100.png │ │ │ ├── ui-icons_004276_256x240.png │ │ │ ├── ui-icons_cc0000_256x240.png │ │ │ └── ui-icons_ffffff_256x240.png │ │ │ └── jquery-ui-1.8.17.custom.css │ └── js │ │ ├── jquery-1.7.1.min.js │ │ └── jquery-ui-1.8.17.custom.min.js ├── jquery.tablesorter.js ├── less-1.2.1.min.js └── markerclusterer.js ├── package-lock.json ├── package.json ├── src ├── definition.ts ├── link.ts ├── node.ts ├── story-plan-organizer.ts └── uuid.ts ├── styles └── styles.css ├── tsconfig.json └── ui.css /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.hg_archival.txt: -------------------------------------------------------------------------------- 1 | repo: a7bdd3a0e318b23e21cdb1633ed114a2a55ecf7b 2 | node: 0e3418716ee4fbe351d8df6d1bdd4e0039d035d9 3 | branch: default 4 | latesttag: null 5 | latesttagdistance: 35 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "endOfLine": "auto", 4 | "jsxSingleQuote": true, 5 | "printWidth": 120, 6 | "proseWrap": "preserve", 7 | "semi": true, 8 | "singleQuote": true, 9 | "tabWidth": 2, 10 | "trailingComma": "all" 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /build/dist/definition.d.ts: -------------------------------------------------------------------------------- 1 | import { UUID } from './uuid.js'; 2 | export declare enum NodeType { 3 | Character = "Character", 4 | Location = "Location", 5 | Organization = "Organization", 6 | Event = "Event", 7 | Story = "Story", 8 | Lore = "Lore" 9 | } 10 | export type Point = { 11 | x: number; 12 | y: number; 13 | }; 14 | export type Color_Hex = `#${string}`; 15 | export type Node = { 16 | id: UUID; 17 | location: Point; 18 | type: NodeType; 19 | name: string; 20 | color: Color_Hex; 21 | }; 22 | export type Character = Node & { 23 | imageSrc: string; 24 | personality: string; 25 | quirk: string; 26 | like: string; 27 | dislike: string; 28 | strength: string; 29 | weakness: string; 30 | flaw: string; 31 | motivation: string; 32 | other: string; 33 | }; 34 | export type Location = Node & { 35 | imageSrc: string; 36 | description: string; 37 | }; 38 | export type Organization = Node & { 39 | objective: string; 40 | detail: string; 41 | }; 42 | export type Event = Node & { 43 | detail: string; 44 | }; 45 | export type Story = Node & { 46 | description: string; 47 | }; 48 | export type Lore = Node & { 49 | detail: string; 50 | }; 51 | export type NodePositionResults = { 52 | top: number; 53 | bottom: number; 54 | left: number; 55 | right: number; 56 | topLeft: Point; 57 | topRight: Point; 58 | bottomLeft: Point; 59 | bottomRight: Point; 60 | }; 61 | export type Link = { 62 | nodeFromId: UUID; 63 | nodeToId: UUID; 64 | }; 65 | export type Dto = { 66 | nodes: Node[]; 67 | links: Link[]; 68 | }; 69 | export type State = { 70 | nodes: Node[]; 71 | nodesCached: HTMLDivElement[]; 72 | links: Link[]; 73 | linesCached: HTMLDivElement[]; 74 | selectedNodeElement: HTMLDivElement | null; 75 | createOngoingLinkId: UUID | null; 76 | deleting: boolean; 77 | }; 78 | export declare const CALCULATION_INCREMENT: number; 79 | -------------------------------------------------------------------------------- /build/dist/definition.js: -------------------------------------------------------------------------------- 1 | export var NodeType; 2 | (function (NodeType) { 3 | NodeType["Character"] = "Character"; 4 | NodeType["Location"] = "Location"; 5 | NodeType["Organization"] = "Organization"; 6 | NodeType["Event"] = "Event"; 7 | NodeType["Story"] = "Story"; 8 | NodeType["Lore"] = "Lore"; 9 | })(NodeType || (NodeType = {})); 10 | export const CALCULATION_INCREMENT = 20; 11 | //# sourceMappingURL=definition.js.map -------------------------------------------------------------------------------- /build/dist/definition.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"definition.js","sourceRoot":"","sources":["../../src/definition.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,QAOX;AAPD,WAAY,QAAQ;IAClB,mCAAuB,CAAA;IACvB,iCAAqB,CAAA;IACrB,yCAA6B,CAAA;IAC7B,2BAAe,CAAA;IACf,2BAAe,CAAA;IACf,yBAAa,CAAA;AACf,CAAC,EAPW,QAAQ,KAAR,QAAQ,QAOnB;AAmFD,MAAM,CAAC,MAAM,qBAAqB,GAAW,EAAE,CAAC"} -------------------------------------------------------------------------------- /build/dist/link.d.ts: -------------------------------------------------------------------------------- 1 | import { State } from './definition.js'; 2 | import { UUID } from './uuid.js'; 3 | export declare const redraw_lines: (state: State) => void; 4 | export declare const add_link: (nodeId1: UUID, nodeId2: UUID, state: State) => void; 5 | -------------------------------------------------------------------------------- /build/dist/link.js: -------------------------------------------------------------------------------- 1 | import { CALCULATION_INCREMENT } from './definition.js'; 2 | import { get_node, get_node_element } from './node.js'; 3 | import { refresh } from './story-plan-organizer.js'; 4 | const does_link_exist = (nodeId1, nodeId2, links) => { 5 | for (const link of links) { 6 | if ((nodeId1 === link.nodeFromId && nodeId2 === link.nodeToId) || 7 | (nodeId2 === link.nodeFromId && nodeId1 === link.nodeToId)) { 8 | return true; 9 | } 10 | } 11 | return false; 12 | }; 13 | const calculate_element_positions = (node) => { 14 | const element = get_node_element(node.id); 15 | if (element) { 16 | const top = node.location.y; 17 | const bottom = node.location.y + element.offsetHeight; 18 | const left = node.location.x; 19 | const right = node.location.x + element.offsetWidth; 20 | const topLeft = { x: node.location.x, y: node.location.y }; 21 | const topRight = { x: node.location.x + element.offsetWidth, y: node.location.y }; 22 | const bottomLeft = { x: node.location.x, y: node.location.y + element.offsetHeight }; 23 | const bottomRight = { x: node.location.x + element.offsetWidth, y: node.location.y + element.offsetHeight }; 24 | return { top, bottom, left, right, topLeft, topRight, bottomLeft, bottomRight }; 25 | } 26 | else { 27 | return undefined; 28 | } 29 | }; 30 | const calculate_distance = (point1, point2) => { 31 | const a = point1.x - point2.x; 32 | const b = point1.y - point2.y; 33 | return Math.sqrt(a * a + b * b); 34 | }; 35 | const calculate_shortest_distance_2 = (point, node2) => { 36 | const currentShortestPoint = { point: { x: 0, y: 0 }, distance: 999999999999 }; 37 | const nodePositions2 = calculate_element_positions(node2); 38 | if (nodePositions2) { 39 | // 1. Sweep TopLeft to TopRight 40 | for (let x = nodePositions2.left; x < nodePositions2.right; x = x + CALCULATION_INCREMENT) { 41 | const tempPoint = { x: x, y: nodePositions2.top }; 42 | const distance = calculate_distance(point, tempPoint); 43 | if (distance < currentShortestPoint.distance) { 44 | currentShortestPoint.point = tempPoint; 45 | currentShortestPoint.distance = distance; 46 | } 47 | } 48 | // 2. Sweep TopRight to BottomRight 49 | for (let y = nodePositions2.top; y < nodePositions2.bottom; y = y + CALCULATION_INCREMENT) { 50 | const tempPoint = { x: nodePositions2.right, y: y }; 51 | const distance = calculate_distance(point, tempPoint); 52 | if (distance < currentShortestPoint.distance) { 53 | currentShortestPoint.point = tempPoint; 54 | currentShortestPoint.distance = distance; 55 | } 56 | } 57 | // 3. Sweep BottomLeft to BottomRight 58 | for (let x = nodePositions2.left; x < nodePositions2.right; x = x + CALCULATION_INCREMENT) { 59 | const tempPoint = { x: x, y: nodePositions2.bottom }; 60 | const distance = calculate_distance(point, tempPoint); 61 | if (distance < currentShortestPoint.distance) { 62 | currentShortestPoint.point = tempPoint; 63 | currentShortestPoint.distance = distance; 64 | } 65 | } 66 | // 4. Sweep TopLeft to BottomLeft 67 | for (let y = nodePositions2.top; y < nodePositions2.bottom; y = y + CALCULATION_INCREMENT) { 68 | const tempPoint = { x: nodePositions2.left, y: y }; 69 | const distance = calculate_distance(point, tempPoint); 70 | if (distance < currentShortestPoint.distance) { 71 | currentShortestPoint.point = tempPoint; 72 | currentShortestPoint.distance = distance; 73 | } 74 | } 75 | } 76 | return currentShortestPoint; 77 | }; 78 | const calculate_shortest_distance = (node1, node2) => { 79 | const currentShortestPoints = { point1: { x: 0, y: 0 }, point2: { x: 0, y: 0 }, distance: 999999999999 }; 80 | const nodePositions1 = calculate_element_positions(node1); 81 | if (nodePositions1) { 82 | // 1. Sweep TopLeft to TopRight 83 | for (let x = nodePositions1.left; x < nodePositions1.right; x = x + CALCULATION_INCREMENT) { 84 | const tempPoint = { x: x, y: nodePositions1.top }; 85 | const result = calculate_shortest_distance_2(tempPoint, node2); 86 | if (result.distance < currentShortestPoints.distance) { 87 | currentShortestPoints.point1 = tempPoint; 88 | currentShortestPoints.point2 = result.point; 89 | currentShortestPoints.distance = result.distance; 90 | } 91 | } 92 | // 2. Sweep TopRight to BottomRight 93 | for (let y = nodePositions1.top; y < nodePositions1.bottom; y = y + CALCULATION_INCREMENT) { 94 | const tempPoint = { x: nodePositions1.right, y: y }; 95 | const result = calculate_shortest_distance_2(tempPoint, node2); 96 | if (result.distance < currentShortestPoints.distance) { 97 | currentShortestPoints.point1 = tempPoint; 98 | currentShortestPoints.point2 = result.point; 99 | currentShortestPoints.distance = result.distance; 100 | } 101 | } 102 | // 3. Sweep BottomLeft to BottomRight 103 | for (let x = nodePositions1.left; x < nodePositions1.right; x = x + CALCULATION_INCREMENT) { 104 | const tempPoint = { x: x, y: nodePositions1.bottom }; 105 | const result = calculate_shortest_distance_2(tempPoint, node2); 106 | if (result.distance < currentShortestPoints.distance) { 107 | currentShortestPoints.point1 = tempPoint; 108 | currentShortestPoints.point2 = result.point; 109 | currentShortestPoints.distance = result.distance; 110 | } 111 | } 112 | // 4. Sweep TopLeft to BottomLeft 113 | for (let y = nodePositions1.top; y < nodePositions1.bottom; y = y + CALCULATION_INCREMENT) { 114 | const tempPoint = { x: nodePositions1.left, y: y }; 115 | const result = calculate_shortest_distance_2(tempPoint, node2); 116 | if (result.distance < currentShortestPoints.distance) { 117 | currentShortestPoints.point1 = tempPoint; 118 | currentShortestPoints.point2 = result.point; 119 | currentShortestPoints.distance = result.distance; 120 | } 121 | } 122 | } 123 | return { point1: currentShortestPoints.point1, point2: currentShortestPoints.point2 }; 124 | }; 125 | const create_line = (nodeId1, nodeId2, state) => { 126 | const node1 = get_node(nodeId1, state.nodes); 127 | const node2 = get_node(nodeId2, state.nodes); 128 | if (node1 && node2) { 129 | const newElement = document.createElement('div'); 130 | const newLine = document.body.appendChild(newElement); 131 | newLine.className = 'line'; 132 | const points = calculate_shortest_distance(node1, node2); 133 | const gradientId = nodeId1 + '_' + nodeId2; 134 | newLine.innerHTML = ` 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | `; 145 | state.linesCached.push(newElement); 146 | const lineElement = newLine.getElementsByTagName('line')[0]; 147 | if (lineElement) { 148 | const nodeElement1 = get_node_element(nodeId1); 149 | const nodeElement2 = get_node_element(nodeId2); 150 | if (state.selectedNodeElement) { 151 | if (nodeElement1 === state.selectedNodeElement || nodeElement2 === state.selectedNodeElement) { 152 | lineElement.classList.add('line-highlighted'); 153 | lineElement.classList.remove('line-unhighlighted'); 154 | } 155 | else { 156 | lineElement.classList.remove('line-highlighted'); 157 | lineElement.classList.add('line-unhighlighted'); 158 | } 159 | } 160 | else { 161 | lineElement.classList.remove('line-highlighted'); 162 | lineElement.classList.remove('line-unhighlighted'); 163 | } 164 | lineElement.addEventListener('click', () => { 165 | if (state.deleting) { 166 | delete_link(nodeId1, nodeId2, state); 167 | } 168 | }); 169 | } 170 | } 171 | }; 172 | const delete_link = (nodeId1, nodeId2, state) => { 173 | for (let i = state.links.length - 1; i >= 0; i--) { 174 | const link = state.links[i]; 175 | if ((nodeId1 === link.nodeFromId && nodeId2 === link.nodeToId) || 176 | (nodeId2 === link.nodeFromId && nodeId1 === link.nodeToId)) { 177 | state.links.splice(i, 1); 178 | } 179 | } 180 | refresh(state); 181 | }; 182 | export const redraw_lines = (state) => { 183 | for (const line of state.linesCached) { 184 | line.remove(); 185 | } 186 | state.linesCached = []; 187 | for (const link of state.links) { 188 | create_line(link.nodeFromId, link.nodeToId, state); 189 | } 190 | }; 191 | export const add_link = (nodeId1, nodeId2, state) => { 192 | if (nodeId1 && nodeId2 && !does_link_exist(nodeId1, nodeId2, state.links)) { 193 | state.links.push({ nodeFromId: nodeId1, nodeToId: nodeId2 }); 194 | refresh(state); 195 | } 196 | }; 197 | //# sourceMappingURL=link.js.map -------------------------------------------------------------------------------- /build/dist/link.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/link.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /build/dist/node.d.ts: -------------------------------------------------------------------------------- 1 | import { Color_Hex, Node, NodeType, Point, State } from './definition.js'; 2 | import { UUID } from './uuid.js'; 3 | export declare const get_node: (id: UUID, nodes: Node[]) => Node | undefined; 4 | export declare const get_node_element: (id: UUID) => HTMLDivElement | null; 5 | export declare const add_node: (location: Point, type: NodeType, state: State) => void; 6 | export declare const get_icon: (type: NodeType) => { 7 | color: Color_Hex; 8 | backgroundColor: Color_Hex; 9 | text: string; 10 | }; 11 | export declare const create_node_element: (node: Node, state: State) => void; 12 | -------------------------------------------------------------------------------- /build/dist/node.js: -------------------------------------------------------------------------------- 1 | import { NodeType, } from './definition.js'; 2 | import { add_link, redraw_lines } from './link.js'; 3 | import { refresh, validate } from './story-plan-organizer.js'; 4 | import { randomUUID } from './uuid.js'; 5 | export const get_node = (id, nodes) => { 6 | let foundNode; 7 | for (const node of nodes) { 8 | if (node.id === id) { 9 | foundNode = node; 10 | break; 11 | } 12 | } 13 | return foundNode; 14 | }; 15 | export const get_node_element = (id) => { 16 | const htmlElement = document.getElementById(id); 17 | return htmlElement ? htmlElement : null; 18 | }; 19 | export const add_node = (location, type, state) => { 20 | const base = { 21 | id: randomUUID(), 22 | location, 23 | type, 24 | name: '', 25 | color: '#FFFFFF', 26 | }; 27 | let node; 28 | switch (type) { 29 | case NodeType.Character: 30 | { 31 | node = Object.assign(Object.assign({}, base), { imageSrc: '', personality: '', quirk: '', like: '', dislike: '', strength: '', weakness: '', flaw: '', motivation: '', other: '' }); 32 | } 33 | break; 34 | case NodeType.Location: 35 | { 36 | node = Object.assign(Object.assign({}, base), { imageSrc: '', description: '' }); 37 | } 38 | break; 39 | case NodeType.Organization: 40 | { 41 | node = Object.assign(Object.assign({}, base), { objective: '', detail: '' }); 42 | } 43 | break; 44 | case NodeType.Event: 45 | { 46 | node = Object.assign(Object.assign({}, base), { detail: '' }); 47 | } 48 | break; 49 | case NodeType.Story: 50 | { 51 | node = Object.assign(Object.assign({}, base), { description: '' }); 52 | } 53 | break; 54 | case NodeType.Lore: 55 | { 56 | node = Object.assign(Object.assign({}, base), { detail: '' }); 57 | } 58 | break; 59 | default: 60 | break; 61 | } 62 | if (node) { 63 | state.nodes.push(node); 64 | validate(state); 65 | } 66 | }; 67 | export const get_icon = (type) => { 68 | var _a; 69 | let color; 70 | const backgroundColor = '#DEF4FF'; 71 | switch (type) { 72 | case NodeType.Character: 73 | { 74 | color = '#0000FF'; 75 | } 76 | break; 77 | case NodeType.Location: 78 | { 79 | color = '#1BD900'; 80 | } 81 | break; 82 | case NodeType.Organization: 83 | { 84 | color = '#FFA500'; 85 | } 86 | break; 87 | case NodeType.Event: 88 | { 89 | color = '#FF0000'; 90 | } 91 | break; 92 | case NodeType.Story: 93 | { 94 | color = '#C700C7'; 95 | } 96 | break; 97 | case NodeType.Lore: 98 | { 99 | color = '#008080'; 100 | } 101 | break; 102 | default: 103 | { 104 | color = '#FFFFFF'; 105 | } 106 | break; 107 | } 108 | const text = ((_a = document.getElementById('create-node-' + NodeType[type])) === null || _a === void 0 ? void 0 : _a.getElementsByClassName('material-icons')[0]).innerText; 109 | return { color, backgroundColor, text }; 110 | }; 111 | export const create_node_element = (node, state) => { 112 | const newElement = document.createElement('div'); 113 | const newNodeElement = document.body.appendChild(newElement); 114 | newNodeElement.id = node.id; 115 | newNodeElement.className = 'node'; 116 | newNodeElement.style.top = node.location.y + 'px'; 117 | newNodeElement.style.left = node.location.x + 'px'; 118 | newNodeElement.style.borderColor = node.color; 119 | const icon = get_icon(node.type); 120 | newNodeElement.innerHTML = ` 121 |
122 |
123 | ${icon.text} 124 | ${NodeType[node.type]} 125 |
126 | 127 | 128 |
129 | `; 130 | switch (node.type) { 131 | case NodeType.Character: 132 | { 133 | if (node.imageSrc) { 134 | newNodeElement.innerHTML += ` 135 | 136 | `; 137 | } 138 | newNodeElement.innerHTML += ` 139 | 140 |
141 | 142 |
143 | 144 |
145 | 146 |
147 | 148 |
149 | 150 | 151 |
152 | 153 |
154 | 155 | 156 |
157 | 158 |
159 | 160 |
161 | 162 |
163 | 164 |
165 | 166 |
167 | 168 |
169 | `; 170 | const textarea_personality = newNodeElement.getElementsByTagName('textarea')[0]; 171 | textarea_personality.addEventListener('input', () => { 172 | node.personality = textarea_personality.value; 173 | }, false); 174 | const textarea_quirk = newNodeElement.getElementsByTagName('textarea')[1]; 175 | textarea_quirk.addEventListener('input', () => { 176 | node.quirk = textarea_quirk.value; 177 | }, false); 178 | const textarea_like = newNodeElement.getElementsByTagName('textarea')[2]; 179 | textarea_like.addEventListener('input', () => { 180 | node.like = textarea_like.value; 181 | }, false); 182 | const textarea_dislike = newNodeElement.getElementsByTagName('textarea')[3]; 183 | textarea_dislike.addEventListener('input', () => { 184 | node.dislike = textarea_dislike.value; 185 | }, false); 186 | const textarea_strength = newNodeElement.getElementsByTagName('textarea')[4]; 187 | textarea_strength.addEventListener('input', () => { 188 | node.strength = textarea_strength.value; 189 | }, false); 190 | const textarea_weakness = newNodeElement.getElementsByTagName('textarea')[5]; 191 | textarea_weakness.addEventListener('input', () => { 192 | node.weakness = textarea_weakness.value; 193 | }, false); 194 | const textarea_flaw = newNodeElement.getElementsByTagName('textarea')[6]; 195 | textarea_flaw.addEventListener('input', () => { 196 | node.flaw = textarea_flaw.value; 197 | }, false); 198 | const textarea_motivation = newNodeElement.getElementsByTagName('textarea')[7]; 199 | textarea_motivation.addEventListener('input', () => { 200 | node.motivation = textarea_motivation.value; 201 | }, false); 202 | const textarea_other = newNodeElement.getElementsByTagName('textarea')[8]; 203 | textarea_other.addEventListener('input', () => { 204 | node.other = textarea_other.value; 205 | }, false); 206 | } 207 | break; 208 | case NodeType.Location: 209 | { 210 | if (node.imageSrc) { 211 | newNodeElement.innerHTML += ` 212 | 213 | `; 214 | } 215 | newNodeElement.innerHTML += ` 216 | 217 |
218 | 219 |
220 | `; 221 | const textarea_description = newNodeElement.getElementsByTagName('textarea')[0]; 222 | textarea_description.addEventListener('input', () => { 223 | node.description = textarea_description.value; 224 | }, false); 225 | } 226 | break; 227 | case NodeType.Organization: 228 | { 229 | newNodeElement.innerHTML += ` 230 | 231 |
232 | 233 |
234 | 235 |
236 | 237 |
238 | `; 239 | const textarea_objective = newNodeElement.getElementsByTagName('textarea')[0]; 240 | textarea_objective.addEventListener('input', () => { 241 | node.objective = textarea_objective.value; 242 | }, false); 243 | const textarea_detail = newNodeElement.getElementsByTagName('textarea')[1]; 244 | textarea_detail.addEventListener('input', () => { 245 | node.detail = textarea_detail.value; 246 | }, false); 247 | } 248 | break; 249 | case NodeType.Event: 250 | { 251 | newNodeElement.innerHTML += ` 252 | 253 |
254 | 255 |
256 | `; 257 | const textarea_detail = newNodeElement.getElementsByTagName('textarea')[0]; 258 | textarea_detail.addEventListener('input', () => { 259 | node.detail = textarea_detail.value; 260 | }, false); 261 | } 262 | break; 263 | case NodeType.Story: 264 | { 265 | newNodeElement.innerHTML += ` 266 | 267 |
268 | 269 |
270 | `; 271 | const textarea_description = newNodeElement.getElementsByTagName('textarea')[0]; 272 | textarea_description.addEventListener('input', () => { 273 | node.description = textarea_description.value; 274 | }, false); 275 | } 276 | break; 277 | case NodeType.Lore: 278 | { 279 | newNodeElement.innerHTML += ` 280 | 281 |
282 | 283 |
284 | `; 285 | const textarea_detail = newNodeElement.getElementsByTagName('textarea')[0]; 286 | textarea_detail.addEventListener('input', () => { 287 | node.detail = textarea_detail.value; 288 | }, false); 289 | } 290 | break; 291 | default: 292 | break; 293 | } 294 | // addEventListeners need to be after all the += innerHTML 295 | const input_name = newNodeElement.getElementsByClassName('node-name')[0]; 296 | input_name.addEventListener('input', () => { 297 | node.name = input_name.value; 298 | }, false); 299 | const input_color = newNodeElement.getElementsByClassName('node-color')[0]; 300 | input_color.addEventListener('input', () => { 301 | node.color = input_color.value; 302 | newNodeElement.style.borderColor = node.color; 303 | redraw_lines(state); 304 | }, false); 305 | setup_accordions(newNodeElement, state); 306 | drag_node_element(newElement, state); 307 | state.nodesCached.push(newElement); 308 | }; 309 | const setup_accordions = (nodeElement, state) => { 310 | const accordions = nodeElement.getElementsByClassName('accordion'); 311 | for (let i = 0; i < accordions.length; i++) { 312 | accordions[i].addEventListener('click', () => { 313 | accordions[i].classList.toggle('active'); 314 | const panel = accordions[i].nextElementSibling; 315 | if (panel) { 316 | if (panel.style.maxHeight === '0px') { 317 | panel.style.maxHeight = '100%'; 318 | } 319 | else { 320 | panel.style.maxHeight = '0px'; 321 | } 322 | } 323 | const textareas = panel.getElementsByTagName('textarea'); 324 | for (let i = 0; i < textareas.length; i++) { 325 | const textarea = textareas[i]; 326 | textarea.setAttribute('style', textarea.getAttribute('style') + 'height:' + textarea.scrollHeight + 'px; overflow-y:hidden;'); 327 | textarea.addEventListener('input', () => { 328 | textarea.style.height = 'auto'; 329 | textarea.style.height = textarea.scrollHeight + 'px'; 330 | }, false); 331 | } 332 | redraw_lines(state); 333 | }); 334 | } 335 | }; 336 | const drag_node_element = (element, state) => { 337 | let pos1 = 0; 338 | let pos2 = 0; 339 | let pos3 = 0; 340 | let pos4 = 0; 341 | const moveElement = element.getElementsByClassName('move')[0]; 342 | moveElement.onmousedown = dragMouseDown; 343 | moveElement.addEventListener('mouseup', (event) => { 344 | if (event.button === 2) { 345 | // Right mouse button 346 | if (element.id && state.createOngoingLinkId) { 347 | add_link(element.id, state.createOngoingLinkId, state); 348 | } 349 | state.createOngoingLinkId = null; 350 | } 351 | }); 352 | function dragMouseDown(event) { 353 | event = event || window.event; 354 | event.preventDefault(); 355 | if (event.button === 0) { 356 | // Left mouse button 357 | if (state.deleting) { 358 | delete_node(element, state); 359 | return; 360 | } 361 | if (element !== state.selectedNodeElement) { 362 | state.selectedNodeElement = element; 363 | } 364 | refresh(state); 365 | pos3 = event.clientX; 366 | pos4 = event.clientY; 367 | document.onmouseup = closeDragElement; 368 | document.onmousemove = elementDrag; 369 | } 370 | else if (event.button === 2) { 371 | // Right mouse button 372 | state.createOngoingLinkId = element.id; 373 | } 374 | } 375 | function elementDrag(event) { 376 | event = event || window.event; 377 | event.preventDefault(); 378 | pos1 = pos3 - event.clientX; 379 | pos2 = pos4 - event.clientY; 380 | pos3 = event.clientX; 381 | pos4 = event.clientY; 382 | const node = get_node(element.id, state.nodes); 383 | if (node) { 384 | node.location.x = element.offsetLeft - pos1; 385 | node.location.y = element.offsetTop - pos2; 386 | element.style.top = node.location.y + 'px'; 387 | element.style.left = node.location.x + 'px'; 388 | redraw_lines(state); 389 | } 390 | } 391 | function closeDragElement() { 392 | document.onmouseup = null; 393 | document.onmousemove = null; 394 | } 395 | }; 396 | const delete_node = (nodeElement, state) => { 397 | if (nodeElement === state.selectedNodeElement) { 398 | state.selectedNodeElement = null; 399 | } 400 | const nodeFound = get_node(nodeElement.id, state.nodes); 401 | if (nodeFound) { 402 | const index = state.nodes.indexOf(nodeFound); 403 | if (index !== -1) { 404 | state.nodes.splice(index, 1); 405 | } 406 | } 407 | validate(state); 408 | }; 409 | //# sourceMappingURL=node.js.map -------------------------------------------------------------------------------- /build/dist/node.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /build/dist/story-plan-organizer.d.ts: -------------------------------------------------------------------------------- 1 | import { State } from './definition.js'; 2 | export declare const validate: (state: State) => void; 3 | export declare const refresh: (state: State) => void; 4 | -------------------------------------------------------------------------------- /build/dist/story-plan-organizer.js: -------------------------------------------------------------------------------- 1 | var _a, _b; 2 | import { NodeType } from './definition.js'; 3 | import { redraw_lines } from './link.js'; 4 | import { add_node, create_node_element, get_icon, get_node, get_node_element } from './node.js'; 5 | // Does not handle refreshing, just validating 6 | export const validate = (state) => { 7 | // Validate node elements 8 | for (const node of state.nodes) { 9 | const nodeElement = get_node_element(node.id); 10 | if (!nodeElement) { 11 | create_node_element(node, state); 12 | } 13 | } 14 | for (let i = state.nodesCached.length - 1; i >= 0; i--) { 15 | const nodeElement = state.nodesCached[i]; 16 | const node = get_node(nodeElement.id, state.nodes); 17 | if (!node) { 18 | const index = state.nodesCached.indexOf(nodeElement); 19 | if (index !== -1) { 20 | state.nodesCached.splice(index, 1); 21 | } 22 | nodeElement.remove(); 23 | } 24 | } 25 | // Validate links 26 | for (let i = state.links.length - 1; i >= 0; i--) { 27 | const link = state.links[i]; 28 | const validNode1 = get_node(link.nodeFromId, state.nodes) ? true : false; 29 | const validNode2 = get_node(link.nodeToId, state.nodes) ? true : false; 30 | if (!validNode1 || !validNode2) { 31 | state.links.splice(i, 1); 32 | } 33 | } 34 | // Validate highlights and redraw lines 35 | refresh(state); 36 | }; 37 | export const refresh = (state) => { 38 | for (const nodeElement of state.nodesCached) { 39 | if (state.selectedNodeElement) { 40 | if (nodeElement === state.selectedNodeElement) { 41 | state.selectedNodeElement.classList.add('node-highlighted'); 42 | state.selectedNodeElement.classList.remove('node-unhighlighted'); 43 | } 44 | else { 45 | nodeElement.classList.remove('node-highlighted'); 46 | nodeElement.classList.add('node-unhighlighted'); 47 | } 48 | } 49 | else { 50 | nodeElement.classList.remove('node-highlighted'); 51 | nodeElement.classList.remove('node-unhighlighted'); 52 | } 53 | } 54 | if (state.selectedNodeElement) { 55 | const connectedNodeIds = []; 56 | for (const link of state.links) { 57 | if (link.nodeFromId === state.selectedNodeElement.id) { 58 | connectedNodeIds.push(link.nodeToId); 59 | } 60 | else if (link.nodeToId === state.selectedNodeElement.id) { 61 | connectedNodeIds.push(link.nodeFromId); 62 | } 63 | } 64 | for (const nodeId of connectedNodeIds) { 65 | const nodeElement = get_node_element(nodeId); 66 | if (nodeElement) { 67 | nodeElement.classList.add('node-highlighted'); 68 | nodeElement.classList.remove('node-unhighlighted'); 69 | } 70 | } 71 | } 72 | for (const node of state.nodes) { 73 | if (node.location.x < 0) { 74 | node.location.x = 0; 75 | const nodeElement = get_node_element(node.id); 76 | if (nodeElement) { 77 | nodeElement.style.left = node.location.x.toString() + 'px'; 78 | } 79 | } 80 | if (node.location.y < 110) { 81 | node.location.y = 110; 82 | const nodeElement = get_node_element(node.id); 83 | if (nodeElement) { 84 | nodeElement.style.top = node.location.y.toString() + 'px'; 85 | } 86 | } 87 | } 88 | redraw_lines(state); 89 | }; 90 | const state = { 91 | nodes: [], 92 | nodesCached: [], 93 | links: [], 94 | linesCached: [], 95 | selectedNodeElement: null, 96 | createOngoingLinkId: null, 97 | deleting: false, 98 | }; 99 | window.onbeforeunload = function (event) { 100 | event.preventDefault(); 101 | }; 102 | document.addEventListener('contextmenu', (event) => event.preventDefault()); 103 | window.addEventListener('keydown', (event) => keydownResponse(event, state), false); 104 | window.addEventListener('keyup', (event) => keyupResponse(event, state), false); 105 | function keydownResponse(event, state) { 106 | if (event.key === 'Escape') { 107 | state.selectedNodeElement = null; 108 | refresh(state); 109 | } 110 | if (event.key === 'd') { 111 | state.deleting = true; 112 | } 113 | } 114 | function keyupResponse(event, state) { 115 | if (event.key === 'd') { 116 | state.deleting = false; 117 | } 118 | } 119 | // Loading Toolbar create node button icon colors 120 | for (const nodeType of [ 121 | NodeType.Character, 122 | NodeType.Location, 123 | NodeType.Organization, 124 | NodeType.Event, 125 | NodeType.Story, 126 | NodeType.Lore, 127 | ]) { 128 | const button_create = document.getElementById('create-node-' + NodeType[nodeType]); 129 | button_create === null || button_create === void 0 ? void 0 : button_create.addEventListener('click', (event) => { 130 | add_node({ x: event.pageX, y: event.pageY + 100 }, nodeType, state); 131 | }); 132 | (button_create === null || button_create === void 0 ? void 0 : button_create.firstElementChild).style.color = get_icon(nodeType).color; 133 | } 134 | // Export 135 | const download = (fileName, text) => { 136 | const element = document.createElement('a'); 137 | element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(text)); 138 | element.setAttribute('download', fileName); 139 | element.style.display = 'none'; 140 | document.body.appendChild(element); 141 | element.click(); 142 | document.body.removeChild(element); 143 | }; 144 | (_a = document.getElementById('export')) === null || _a === void 0 ? void 0 : _a.addEventListener('click', () => { 145 | console.log(state); 146 | const fileName = 'story.json'; 147 | const dto = { nodes: state.nodes, links: state.links }; 148 | const fileContent = JSON.stringify(dto, null, 2); 149 | download(fileName, fileContent); 150 | }); 151 | // Import 152 | const validJson = (json) => { 153 | try { 154 | JSON.parse(json); 155 | } 156 | catch (e) { 157 | return false; 158 | } 159 | return true; 160 | }; 161 | const load = (dto, state) => { 162 | reset(state); 163 | state.nodes = dto.nodes; 164 | state.links = dto.links; 165 | validate(state); 166 | }; 167 | const reset = (state) => { 168 | state.nodes = []; 169 | for (const nodeElement of state.nodesCached) { 170 | nodeElement.remove(); 171 | } 172 | state.links = []; 173 | for (const lineElement of state.linesCached) { 174 | lineElement.remove(); 175 | } 176 | validate(state); 177 | state.selectedNodeElement = null; 178 | state.createOngoingLinkId = null; 179 | state.deleting = false; 180 | }; 181 | document.getElementById('inputLoadFile').onchange = (event) => { 182 | const reader = new FileReader(); 183 | reader.onload = onReaderLoad; 184 | const tempElement = event.target; 185 | if (tempElement && tempElement.files) { 186 | reader.readAsText(tempElement.files[0]); 187 | } 188 | function onReaderLoad(event) { 189 | var _a, _b, _c, _d, _e; 190 | console.log(event); 191 | if (event.target && event.target.result) { 192 | const jsonString = event.target.result; 193 | if (validJson(jsonString)) { 194 | const jsonObject = JSON.parse(jsonString); 195 | load(jsonObject, state); 196 | const button = document.getElementById('button-load'); 197 | button.disabled = true; 198 | button.innerText = ''; 199 | // To maximize the textareas the next time user shows all 200 | (_a = document.getElementById('toggle-visibility')) === null || _a === void 0 ? void 0 : _a.click(); 201 | (_b = document.getElementById('toggle-visibility')) === null || _b === void 0 ? void 0 : _b.click(); 202 | (_c = document.getElementById('toggle-visibility')) === null || _c === void 0 ? void 0 : _c.click(); 203 | (_d = document.getElementById('toggle-visibility')) === null || _d === void 0 ? void 0 : _d.click(); 204 | (_e = document.getElementById('toggle-visibility')) === null || _e === void 0 ? void 0 : _e.click(); 205 | } 206 | } 207 | } 208 | }; 209 | // Hide / Show All 210 | let toggleVisibility = 0; 211 | (_b = document.getElementById('toggle-visibility')) === null || _b === void 0 ? void 0 : _b.addEventListener('click', () => { 212 | var _a, _b; 213 | const accordions = document.getElementsByClassName('accordion'); 214 | for (let i = 0; i < accordions.length; i++) { 215 | const panel = accordions[i].nextElementSibling; 216 | if (panel) { 217 | if (toggleVisibility % 3 === 0) { 218 | // Hide All 219 | if (panel.style.maxHeight !== '0px') { 220 | accordions[i].click(); 221 | } 222 | } 223 | else if (toggleVisibility % 3 === 1) { 224 | // Show Events, otherwise Hide 225 | const id = (_a = accordions[i].parentElement) === null || _a === void 0 ? void 0 : _a.id; 226 | if (id && ((_b = get_node(id, state.nodes)) === null || _b === void 0 ? void 0 : _b.type) === NodeType.Event) { 227 | const textarea = panel.getElementsByTagName('textarea')[0]; 228 | if (panel.style.maxHeight === '0px' && textarea.value !== '') { 229 | accordions[i].click(); 230 | } 231 | } 232 | else if (panel.style.maxHeight !== '0px') { 233 | accordions[i].click(); 234 | } 235 | } 236 | else if (toggleVisibility % 3 === 2) { 237 | // Show All 238 | const textarea = panel.getElementsByTagName('textarea')[0]; 239 | const textareaRight = panel.getElementsByTagName('textarea')[1]; 240 | if (panel.style.maxHeight === '0px' && 241 | (textarea.value !== '' || (textareaRight && textareaRight.value !== ''))) { 242 | accordions[i].click(); 243 | } 244 | } 245 | } 246 | } 247 | ++toggleVisibility; 248 | }); 249 | //# sourceMappingURL=story-plan-organizer.js.map -------------------------------------------------------------------------------- /build/dist/story-plan-organizer.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"story-plan-organizer.js","sourceRoot":"","sources":["../../src/story-plan-organizer.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /build/dist/uuid.d.ts: -------------------------------------------------------------------------------- 1 | export type UUID = `${string}-${string}-${string}-${string}-${string}`; 2 | export declare const randomUUID: () => UUID; 3 | -------------------------------------------------------------------------------- /build/dist/uuid.js: -------------------------------------------------------------------------------- 1 | // Note: `@types/node/crypto` doesn't seem to work with .ts when bundled, it cannot be imported properly when viewed from the browser 2 | export const randomUUID = () => { 3 | // https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid 4 | // Timestamp 5 | let d = new Date().getTime(); 6 | // Time in microseconds since page-load or 0 if unsupported 7 | let d2 = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0; 8 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 9 | // Random number between 0 and 16 10 | let r = Math.random() * 16; 11 | if (d > 0) { 12 | // Use timestamp until depleted 13 | r = (d + r) % 16 | 0; 14 | d = Math.floor(d / 16); 15 | } 16 | else { 17 | // Use microseconds since page-load if supported 18 | r = (d2 + r) % 16 | 0; 19 | d2 = Math.floor(d2 / 16); 20 | } 21 | return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16); 22 | }); 23 | }; 24 | //# sourceMappingURL=uuid.js.map -------------------------------------------------------------------------------- /build/dist/uuid.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../src/uuid.ts"],"names":[],"mappings":"AAAA,qIAAqI;AAIrI,MAAM,CAAC,MAAM,UAAU,GAAG,GAAS,EAAE;IACnC,yEAAyE;IACzE,YAAY;IACZ,IAAI,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;IAC7B,2DAA2D;IAC3D,IAAI,EAAE,GAAG,CAAC,OAAO,WAAW,KAAK,WAAW,IAAI,WAAW,CAAC,GAAG,IAAI,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAClG,OAAO,sCAAsC,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC;QACxE,iCAAiC;QACjC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,+BAA+B;YAC/B,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACrB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,gDAAgD;YAChD,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACtB,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACxD,CAAC,CAAS,CAAC;AACb,CAAC,CAAC"} -------------------------------------------------------------------------------- /build/tsconfig.tsbuildinfo: -------------------------------------------------------------------------------- 1 | {"program":{"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.dom.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2016.intl.d.ts","../node_modules/typescript/lib/lib.es2017.date.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2019.intl.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.decorators.d.ts","../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../src/uuid.ts","../src/definition.ts","../src/story-plan-organizer.ts","../src/node.ts","../src/link.ts"],"fileInfos":[{"version":"824cb491a40f7e8fdeb56f1df5edf91b23f3e3ee6b4cde84d4a99be32338faee","affectsGlobalScope":true},"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","9a68c0c07ae2fa71b44384a839b7b8d81662a236d4b9ac30916718f7510b1b2d","5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4",{"version":"87d693a4920d794a73384b3c779cadcb8548ac6945aa7a925832fe2418c9527a","affectsGlobalScope":true},{"version":"138fb588d26538783b78d1e3b2c2cc12d55840b97bf5e08bca7f7a174fbe2f17","affectsGlobalScope":true},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true},{"version":"4443e68b35f3332f753eacc66a04ac1d2053b8b035a0e0ac1d455392b5e243b3","affectsGlobalScope":true},{"version":"bc47685641087c015972a3f072480889f0d6c65515f12bd85222f49a98952ed7","affectsGlobalScope":true},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true},{"version":"93495ff27b8746f55d19fcbcdbaccc99fd95f19d057aed1bd2c0cafe1335fbf0","affectsGlobalScope":true},{"version":"6fc23bb8c3965964be8c597310a2878b53a0306edb71d4b5a4dfe760186bcc01","affectsGlobalScope":true},{"version":"ea011c76963fb15ef1cdd7ce6a6808b46322c527de2077b6cfdf23ae6f5f9ec7","affectsGlobalScope":true},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true},{"version":"bb42a7797d996412ecdc5b2787720de477103a0b2e53058569069a0e2bae6c7e","affectsGlobalScope":true},{"version":"4738f2420687fd85629c9efb470793bb753709c2379e5f85bc1815d875ceadcd","affectsGlobalScope":true},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true},{"version":"9fc46429fbe091ac5ad2608c657201eb68b6f1b8341bd6d670047d32ed0a88fa","affectsGlobalScope":true},{"version":"61c37c1de663cf4171e1192466e52c7a382afa58da01b1dc75058f032ddf0839","affectsGlobalScope":true},{"version":"b541a838a13f9234aba650a825393ffc2292dc0fc87681a5d81ef0c96d281e7a","affectsGlobalScope":true},{"version":"b20fe0eca9a4e405f1a5ae24a2b3290b37cf7f21eba6cbe4fc3fab979237d4f3","affectsGlobalScope":true},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true},{"version":"49ed889be54031e1044af0ad2c603d627b8bda8b50c1a68435fe85583901d072","affectsGlobalScope":true},{"version":"e93d098658ce4f0c8a0779e6cab91d0259efb88a318137f686ad76f8410ca270","affectsGlobalScope":true},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true},{"version":"bf14a426dbbf1022d11bd08d6b8e709a2e9d246f0c6c1032f3b2edb9a902adbe","affectsGlobalScope":true},{"version":"5e07ed3809d48205d5b985642a59f2eba47c402374a7cf8006b686f79efadcbd","affectsGlobalScope":true},{"version":"2b72d528b2e2fe3c57889ca7baef5e13a56c957b946906d03767c642f386bbc3","affectsGlobalScope":true},{"version":"8073890e29d2f46fdbc19b8d6d2eb9ea58db9a2052f8640af20baff9afbc8640","affectsGlobalScope":true},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true},{"version":"33358442698bb565130f52ba79bfd3d4d484ac85fe33f3cb1759c54d18201393","affectsGlobalScope":true},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true},{"version":"a8afe9060fa3e6a988fe1f6acebb5661ef7e63c276ec1f6f5c4da31bb70ae1a4","signature":"a415c308e38ed0cce398eb898960ff8310474a4e7db9e2a94e610d49890b74a5"},{"version":"dbb9c3dc32640113de2aa447ef54ee06c473b149ea4e2a100eac5e970ffd9ba0","signature":"e33da25488f15e6de1851c02eb8cb2db61551361645619551f9abb020b4c5bd7"},{"version":"7f4f62dbce693cdd4276430c4f8b28a4c73f65af95bacce38d559930f2c4541e","signature":"1087f3cfcaea8e3133e8c0146b3f3969493b000333586bd09933c75aea8f2266"},{"version":"9092ff8686c098b857eab9500ced141765b2c716ae193acba25e1e3fd06c834e","signature":"3ebe4633b85ae43ab0fb05673d09b0f2ef05ea51528df29a6a538e42eb550f00"},{"version":"5f1f8d7890069809e3c80ed4b381ba9becc790d0c9ff109597340a9da1e8483d","signature":"b4456f5c6e8d3c410b8e0de7eae26b46cefbf40c50103e324e04ea9fc71e7576"}],"root":[[46,50]],"options":{"allowJs":true,"alwaysStrict":true,"declaration":true,"esModuleInterop":true,"module":5,"noEmitOnError":true,"noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitReturns":true,"noImplicitThis":true,"noUnusedLocals":false,"noUnusedParameters":true,"outDir":"./dist","removeComments":false,"rootDir":"../src","skipLibCheck":false,"sourceMap":true,"strict":true,"strictFunctionTypes":true,"strictNullChecks":true,"strictPropertyInitialization":true,"target":2},"fileIdsList":[[46],[46,47,48,49],[46,47,48,50],[46,47,49,50],[46,47],[47]],"referencedMap":[[47,1],[50,2],[49,3],[48,4]],"exportedModulesMap":[[47,1],[50,5],[49,5], [48,6]],"semanticDiagnosticsPerFile":[44,45,8,10,9,2,11,12,13,14,15,16,17,18,3,19,4,20,24,21,22,23,25,26,27,5,28,29,30,31,6,35,32,33,34,36,7,37,42,43,38,39,40,41,1,47,50,49,48,46]},"version":"5.4.5"} -------------------------------------------------------------------------------- /data/sample1.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [ 3 | { 4 | "id": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 5 | "location": { 6 | "x": 694, 7 | "y": 340 8 | }, 9 | "type": "Character", 10 | "name": "Hanako Hoshizora", 11 | "color": "#ff80c0", 12 | "imageSrc": "", 13 | 14 | "personality": "Energetic, optimistic, loyal, strong sense of justice", 15 | "quirk": "Hums anime tunes, twirls hair when stressed", 16 | "like": "Cute things, sweets (taiyaki), fashion (Harajuku)", 17 | "dislike": "Bullies, manipulation, burnt toast, spicy food", 18 | "strength": "Optimism, inspiring, agile, quick reflexes", 19 | "weakness": "Naive, impulsive, easily distracted, limited magical power", 20 | "flaw": "Self-doubt, overworks herself", 21 | "motivation": "Protects dreams of the innocent, wants to make the world a better place", 22 | "other": "" 23 | }, 24 | { 25 | "id": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0", 26 | "location": { 27 | "x": 1135, 28 | "y": 340 29 | }, 30 | "type": "Character", 31 | "name": "Yuuri Kageyama", 32 | "color": "#ff8040", 33 | "imageSrc": "", 34 | "personality": "Calm, sarcastic wit, dry humor, secretly admires Hanako's bravery", 35 | "quirk": "Raises an eyebrow skeptically at Hanako's flights of fancy, excellent doodler (often captures funny sketches of Hanako's antics)", 36 | "like": "Reading, spending time at cafes, witty banter, a good mystery novel", 37 | "dislike": "Crowds, overly emotional situations, sugary foods", 38 | "strength": "Level-headed, analytical thinker, keeps Hanako grounded, resourceful", 39 | "weakness": "Can be overly cautious, struggles to express emotions openly", 40 | "flaw": "Sometimes comes across as cynical, lacks self-confidence in her own abilities", 41 | "motivation": "Cares deeply for Hanako and wants to ensure her safety, secretly finds Hanako's magical adventures exciting", 42 | "other": "" 43 | }, 44 | { 45 | "id": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be", 46 | "location": { 47 | "x": 227, 48 | "y": 329 49 | }, 50 | "type": "Character", 51 | "name": "Hoshihikari Amane", 52 | "color": "#ff0080", 53 | "imageSrc": "", 54 | "personality": "Calm, enigmatic, possesses immense knowledge of magic", 55 | "quirk": "Speaks in riddles and proverbs, enjoys sipping green tea while gazing at the stars", 56 | "like": "Peace, tranquility, sharing wisdom with worthy students", 57 | "dislike": "Disruption of the natural balance, misuse of magic for personal gain", 58 | "strength": "Powerful magic user, vast knowledge of celestial lore, excellent teacher", 59 | "weakness": "Can be cryptic and difficult to understand at times, limited physical mobility", 60 | "flaw": "Holds magic in high regard, possibly hesitant to trust humans fully", 61 | "motivation": "Seeks to maintain the balance between the human world and the magical realm, desires to pass on her knowledge to a worthy successor", 62 | "other": "" 63 | }, 64 | { 65 | "id": "ec7f5de0-aa19-421f-812c-77a286737214", 66 | "location": { 67 | "x": 1585, 68 | "y": 341 69 | }, 70 | "type": "Character", 71 | "name": "Akira Sato", 72 | "color": "#00ffff", 73 | "imageSrc": "", 74 | "personality": "Outgoing, enthusiastic, always has a joke or story to tell", 75 | "quirk": "Trips over his own feet frequently, has a knack for getting into trouble (often unintentionally)", 76 | "like": "Spending time with Hanako, trying new foods, participating in local festivals", 77 | "dislike": "Boredom, loneliness, seeing his friends upset", 78 | "strength": "Loyal, supportive, brings out the lighter side in Hanako", 79 | "weakness": "Can be oblivious to social cues, sometimes lacks focus", 80 | "flaw": "Can be a bit clingy and overprotective of Hanako", 81 | "motivation": "Secretly harbors a deeper affection for Hanako, wants to be there for her no matter what, even if it means helping her with her magical battles (despite not knowing the full extent of them)", 82 | "other": "" 83 | }, 84 | { 85 | "id": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 86 | "location": { 87 | "x": 2029, 88 | "y": 340 89 | }, 90 | "type": "Character", 91 | "name": "Yami-D", 92 | "color": "#808000", 93 | "imageSrc": "", 94 | "personality": "Malicious, manipulative, feeds on the weaknesses and desires of others.", 95 | "quirk": "Speaks in glitching fragments of code and advertisements, enjoys toying with its victims before consuming them.", 96 | "like": "Feeding on negative emotions, spreading chaos and despair, corrupting dreams.", 97 | "dislike": "Purity, genuine happiness, acts of selflessness that disrupt its control.", 98 | "strength": "Powerful digital manipulation, can create hypnotic illusions and advertisements, possesses vast knowledge of consumer desires.", 99 | "weakness": "Vulnerable to pure celestial energy, can be disrupted by strong emotions like love and hope. Reliant on technology - a power outage or EMP could be disastrous.", 100 | "flaw": "Overconfident, underestimates the power of human connection and genuine desire.", 101 | "motivation": "Consumes dreams to fuel its own power and existence. Believes humans are weak and easily manipulated by their desires. Wants to control the world by turning everyone's dreams into a twisted reflection of their materialistic wants.", 102 | "other": "" 103 | }, 104 | { 105 | "id": "122ee6a4-0e6f-4822-abd8-60c509ad579d", 106 | "location": { 107 | "x": 1253, 108 | "y": 208 109 | }, 110 | "type": "Location", 111 | "name": "Sakura High School", 112 | "color": "#008040", 113 | "imageSrc": "", 114 | "description": "By day, Sakura High hides its secret as a training ground for magical girls, its classrooms doubling as enchantment chambers under the glow of cherry blossom trees." 115 | }, 116 | { 117 | "id": "6427a20e-226d-4df6-8f12-b4ec82c192c2", 118 | "location": { 119 | "x": 1875, 120 | "y": 186 121 | }, 122 | "type": "Organization", 123 | "name": "Glitching Horde", 124 | "color": "#400000", 125 | "objective": "Seeks to infect the world with corrupted desires, turning humanity into mindless consumers trapped in a digital nightmare.", 126 | "detail": "Yami-D's scattered followers, the Glitching Horde, spread like a digital virus, hijacking dreams and desires through corrupted internet connections." 127 | }, 128 | { 129 | "id": "02d3adf1-5907-4a05-9b8f-37c1e36fe20e", 130 | "location": { 131 | "x": 2191, 132 | "y": 202 133 | }, 134 | "type": "Location", 135 | "name": "Yami-D's lair", 136 | "color": "#804000", 137 | "imageSrc": "", 138 | "description": "Atop a skyscraper shaped like a distorted smartphone screen, Yami-D's lair pulsed with hypnotic advertisements, bleeding digital nightmares into the Tokyo night." 139 | }, 140 | { 141 | "id": "dab3851a-e0f1-4185-b905-c7962780ed1f", 142 | "location": { 143 | "x": 904, 144 | "y": 200 145 | }, 146 | "type": "Organization", 147 | "name": "Dream Weavers", 148 | "color": "#00ff80", 149 | "objective": "Bound by the power of the stars, fight to protect humanity's dreams from the digital corruption of Yami-D and the Glitching Horde.", 150 | "detail": "A network of young women who use celestial magic to safeguard dreams from the clutches of digital nightmares." 151 | }, 152 | { 153 | "id": "5a04aa04-d648-4882-9296-b5a8571d223c", 154 | "location": { 155 | "x": 537, 156 | "y": 226 157 | }, 158 | "type": "Location", 159 | "name": "Star Tea House", 160 | "color": "#ffff00", 161 | "imageSrc": "", 162 | "description": "Disguised as a charming, traditional tea house, the Hoshi Chaya (Star Tea House) serves as a meeting point for the Dream Weavers. Beneath the fragrant steam and delicate teacups, they strategize and share information." 163 | }, 164 | { 165 | "id": "b503d84e-67e5-4448-9f03-5523ccd9c104", 166 | "location": { 167 | "x": 1278, 168 | "y": 1171 169 | }, 170 | "type": "Story", 171 | "name": "Season 1", 172 | "color": "#00ffff", 173 | "description": "In modern Tokyo, bubbly high school student Hanako leads a double life. By day, she serves sugary treats at a maid cafe. By night, she transforms into Hoshizora, a magical girl who joins the Dream Weavers, a hidden network protecting humanity's dreams from the nightmarish digital corruption spread by Yami-D and its Glitching Horde." 174 | }, 175 | { 176 | "id": "45c3cd76-5c96-4a02-84ee-036e8d7bdb66", 177 | "location": { 178 | "x": 694, 179 | "y": 845 180 | }, 181 | "type": "Lore", 182 | "name": "Hoshizora", 183 | "color": "#ff00ff", 184 | "detail": "Hoshizora isn't just a magical girl persona; it's a title and a legacy. Passed down through generations of Dream Weavers, Hoshizora signifies the protector who wields the power of the stars. By day, Hanako might be an ordinary student, but under the moonlight, she transforms, channeling the celestial energy to become the newest Hoshizora, the Star Weaver." 185 | }, 186 | { 187 | "id": "4bd611a5-c114-41b8-b156-e85c3b82010a", 188 | "location": { 189 | "x": 854, 190 | "y": 549 191 | }, 192 | "type": "Lore", 193 | "name": "Dream Weaver Magic", 194 | "color": "#0080c0", 195 | "detail": "Source: Celestial Energy (stars & constellations)\nFuel: Positive Emotions (hope, courage)\nTransformation: Personal Item (imbued with celestial energy) - e.g., Hanako's hair clip\nAbilities:\n- Defense: Shimmering curtains of starlight to block nightmares and attacks\n- Offense: Celestial blasts or constellation-inspired attacks (e.g., Starlight Serenade)\n- Dream Navigation: Enter dreamscapes to fight nightmares directly\n\nLimitations:\n- Negative Emotions weaken magic\n- Limited Power for young Dream Weavers\n- Weak Celestial Connection hinders abilities (e.g., heavy clouds)" 196 | }, 197 | { 198 | "id": "5fcf2528-599c-4330-8b69-30f3dd0e3067", 199 | "location": { 200 | "x": 2180, 201 | "y": 568 202 | }, 203 | "type": "Lore", 204 | "name": "Yami-D's Digital Corruption", 205 | "color": "#400080", 206 | "detail": "Source: Digital Manipulation\nPower:\n- Hypnotic Advertisements: Creates captivating ads that manipulate desires and trap minds in a digital dream world.\n- Corrupted Code Tendrils: Lashes out with corrupted code to physically restrain and harm opponents.\n- Dream Infiltration: Can access and distort human dreams, feeding on negativity and amplifying desires.\n\nWeakness:\n- Pure Celestial Energy: Disrupted by powerful displays of starlight magic used by the Dream Weavers.\n- Technology Reliance: Vulnerable to disruptions in its digital infrastructure (e.g., EMP attack).\n- Overconfidence: Underestimates the power of human connection and genuine desires." 207 | }, 208 | { 209 | "id": "f0e625ce-41fb-4fa8-bcf8-8a2a121de151", 210 | "location": { 211 | "x": 1636, 212 | "y": 720 213 | }, 214 | "type": "Event", 215 | "name": "Witnessing Evil", 216 | "color": "#FFFFFF", 217 | "detail": "Hanako witnesses Yami-D's corrupted advertisements manipulating people in Shibuya Crossing." 218 | }, 219 | { 220 | "id": "570fbc1a-8954-4054-9b30-48615acd3864", 221 | "location": { 222 | "x": 1637, 223 | "y": 552 224 | }, 225 | "type": "Event", 226 | "name": "Confrontation", 227 | "color": "#FFFFFF", 228 | "detail": "As Hoshizora, she confronts Yami-D in a battle across the neon-lit rooftops of Tokyo." 229 | }, 230 | { 231 | "id": "4c0c1746-5fd3-40fa-a70c-1c5396b55f12", 232 | "location": { 233 | "x": 1155, 234 | "y": 551 235 | }, 236 | "type": "Event", 237 | "name": "Battle Assist", 238 | "color": "#FFFFFF", 239 | "detail": "While battling, Hoshizora encounters another Dream Weaver (potentially Yuuri or a new character) who assists her." 240 | }, 241 | { 242 | "id": "5b720633-f29d-46fb-9f82-61161962401b", 243 | "location": { 244 | "x": 725, 245 | "y": 628 246 | }, 247 | "type": "Event", 248 | "name": "Worries", 249 | "color": "#FFFFFF", 250 | "detail": "Back in her normal life, Hanako ponders the growing threat of Yami-D and the responsibility of being Hoshizora." 251 | }, 252 | { 253 | "id": "bf35b66e-10a8-4158-813b-7e632f9b0cdd", 254 | "location": { 255 | "x": 300, 256 | "y": 541 257 | }, 258 | "type": "Event", 259 | "name": "Mentoring", 260 | "color": "#FFFFFF", 261 | "detail": "Hanako seeks guidance from her mentor Hoshihikari to learn more about Yami-D and her powers." 262 | }, 263 | { 264 | "id": "9dd9473a-44a7-42fb-8ce7-d1dcf1d88d81", 265 | "location": { 266 | "x": 780, 267 | "y": 920 268 | }, 269 | "type": "Event", 270 | "name": "Double Life", 271 | "color": "#FFFFFF", 272 | "detail": "Hanako's double life becomes more complicated as she juggles school, her part-time job, and her duties as Hoshizora." 273 | } 274 | ], 275 | "links": [ 276 | { 277 | "nodeFromId": "5a04aa04-d648-4882-9296-b5a8571d223c", 278 | "nodeToId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0" 279 | }, 280 | { 281 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 282 | "nodeToId": "5a04aa04-d648-4882-9296-b5a8571d223c" 283 | }, 284 | { 285 | "nodeFromId": "4bd611a5-c114-41b8-b156-e85c3b82010a", 286 | "nodeToId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693" 287 | }, 288 | { 289 | "nodeFromId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0", 290 | "nodeToId": "4bd611a5-c114-41b8-b156-e85c3b82010a" 291 | }, 292 | { 293 | "nodeFromId": "4bd611a5-c114-41b8-b156-e85c3b82010a", 294 | "nodeToId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be" 295 | }, 296 | { 297 | "nodeFromId": "5a04aa04-d648-4882-9296-b5a8571d223c", 298 | "nodeToId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be" 299 | }, 300 | { 301 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 302 | "nodeToId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be" 303 | }, 304 | { 305 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 306 | "nodeToId": "45c3cd76-5c96-4a02-84ee-036e8d7bdb66" 307 | }, 308 | { 309 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 310 | "nodeToId": "122ee6a4-0e6f-4822-abd8-60c509ad579d" 311 | }, 312 | { 313 | "nodeFromId": "122ee6a4-0e6f-4822-abd8-60c509ad579d", 314 | "nodeToId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0" 315 | }, 316 | { 317 | "nodeFromId": "ec7f5de0-aa19-421f-812c-77a286737214", 318 | "nodeToId": "122ee6a4-0e6f-4822-abd8-60c509ad579d" 319 | }, 320 | { 321 | "nodeFromId": "5a04aa04-d648-4882-9296-b5a8571d223c", 322 | "nodeToId": "dab3851a-e0f1-4185-b905-c7962780ed1f" 323 | }, 324 | { 325 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 326 | "nodeToId": "dab3851a-e0f1-4185-b905-c7962780ed1f" 327 | }, 328 | { 329 | "nodeFromId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be", 330 | "nodeToId": "dab3851a-e0f1-4185-b905-c7962780ed1f" 331 | }, 332 | { 333 | "nodeFromId": "dab3851a-e0f1-4185-b905-c7962780ed1f", 334 | "nodeToId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0" 335 | }, 336 | { 337 | "nodeFromId": "02d3adf1-5907-4a05-9b8f-37c1e36fe20e", 338 | "nodeToId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db" 339 | }, 340 | { 341 | "nodeFromId": "02d3adf1-5907-4a05-9b8f-37c1e36fe20e", 342 | "nodeToId": "6427a20e-226d-4df6-8f12-b4ec82c192c2" 343 | }, 344 | { 345 | "nodeFromId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 346 | "nodeToId": "6427a20e-226d-4df6-8f12-b4ec82c192c2" 347 | }, 348 | { 349 | "nodeFromId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 350 | "nodeToId": "5fcf2528-599c-4330-8b69-30f3dd0e3067" 351 | }, 352 | { 353 | "nodeFromId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0", 354 | "nodeToId": "4c0c1746-5fd3-40fa-a70c-1c5396b55f12" 355 | }, 356 | { 357 | "nodeFromId": "4c0c1746-5fd3-40fa-a70c-1c5396b55f12", 358 | "nodeToId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693" 359 | }, 360 | { 361 | "nodeFromId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 362 | "nodeToId": "570fbc1a-8954-4054-9b30-48615acd3864" 363 | }, 364 | { 365 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 366 | "nodeToId": "570fbc1a-8954-4054-9b30-48615acd3864" 367 | }, 368 | { 369 | "nodeFromId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 370 | "nodeToId": "f0e625ce-41fb-4fa8-bcf8-8a2a121de151" 371 | }, 372 | { 373 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 374 | "nodeToId": "f0e625ce-41fb-4fa8-bcf8-8a2a121de151" 375 | }, 376 | { 377 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 378 | "nodeToId": "5b720633-f29d-46fb-9f82-61161962401b" 379 | }, 380 | { 381 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 382 | "nodeToId": "9dd9473a-44a7-42fb-8ce7-d1dcf1d88d81" 383 | }, 384 | { 385 | "nodeFromId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be", 386 | "nodeToId": "bf35b66e-10a8-4158-813b-7e632f9b0cdd" 387 | }, 388 | { 389 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 390 | "nodeToId": "bf35b66e-10a8-4158-813b-7e632f9b0cdd" 391 | }, 392 | { 393 | "nodeFromId": "b503d84e-67e5-4448-9f03-5523ccd9c104", 394 | "nodeToId": "bf35b66e-10a8-4158-813b-7e632f9b0cdd" 395 | }, 396 | { 397 | "nodeFromId": "f0e625ce-41fb-4fa8-bcf8-8a2a121de151", 398 | "nodeToId": "b503d84e-67e5-4448-9f03-5523ccd9c104" 399 | }, 400 | { 401 | "nodeFromId": "b503d84e-67e5-4448-9f03-5523ccd9c104", 402 | "nodeToId": "570fbc1a-8954-4054-9b30-48615acd3864" 403 | }, 404 | { 405 | "nodeFromId": "5b720633-f29d-46fb-9f82-61161962401b", 406 | "nodeToId": "b503d84e-67e5-4448-9f03-5523ccd9c104" 407 | }, 408 | { 409 | "nodeFromId": "b503d84e-67e5-4448-9f03-5523ccd9c104", 410 | "nodeToId": "9dd9473a-44a7-42fb-8ce7-d1dcf1d88d81" 411 | }, 412 | { 413 | "nodeFromId": "4c0c1746-5fd3-40fa-a70c-1c5396b55f12", 414 | "nodeToId": "b503d84e-67e5-4448-9f03-5523ccd9c104" 415 | } 416 | ] 417 | } -------------------------------------------------------------------------------- /data/sample2.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [ 3 | { 4 | "id": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 5 | "location": { 6 | "x": 2045, 7 | "y": 448 8 | }, 9 | "type": "Character", 10 | "name": "Hanako Hoshizora", 11 | "color": "#ff80c0", 12 | "imageSrc": "", 13 | "personality": "Energetic, optimistic, loyal, strong sense of justice", 14 | "quirk": "Hums anime tunes, twirls hair when stressed", 15 | "like": "Cute things, sweets (taiyaki), fashion (Harajuku)", 16 | "dislike": "Bullies, manipulation, burnt toast, spicy food", 17 | "strength": "Optimism, inspiring, agile, quick reflexes", 18 | "weakness": "Naive, impulsive, easily distracted, limited magical power", 19 | "flaw": "Self-doubt, overworks herself", 20 | "motivation": "Protects dreams of the innocent, wants to make the world a better place", 21 | "other": "" 22 | }, 23 | { 24 | "id": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0", 25 | "location": { 26 | "x": 670, 27 | "y": 303 28 | }, 29 | "type": "Character", 30 | "name": "Yuuri Kageyama", 31 | "color": "#ff8040", 32 | "imageSrc": "", 33 | "personality": "Calm, sarcastic wit, dry humor, secretly admires Hanako's bravery", 34 | "quirk": "Raises an eyebrow skeptically at Hanako's flights of fancy, excellent doodler (often captures funny sketches of Hanako's antics)", 35 | "like": "Reading, spending time at cafes, witty banter, a good mystery novel", 36 | "dislike": "Crowds, overly emotional situations, sugary foods", 37 | "strength": "Level-headed, analytical thinker, keeps Hanako grounded, resourceful", 38 | "weakness": "Can be overly cautious, struggles to express emotions openly", 39 | "flaw": "Sometimes comes across as cynical, lacks self-confidence in her own abilities", 40 | "motivation": "Cares deeply for Hanako and wants to ensure her safety, secretly finds Hanako's magical adventures exciting", 41 | "other": "" 42 | }, 43 | { 44 | "id": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be", 45 | "location": { 46 | "x": 111, 47 | "y": 169 48 | }, 49 | "type": "Character", 50 | "name": "Hoshihikari Amane", 51 | "color": "#ff0080", 52 | "imageSrc": "", 53 | "personality": "Calm, enigmatic, possesses immense knowledge of magic", 54 | "quirk": "Speaks in riddles and proverbs, enjoys sipping green tea while gazing at the stars", 55 | "like": "Peace, tranquility, sharing wisdom with worthy students", 56 | "dislike": "Disruption of the natural balance, misuse of magic for personal gain", 57 | "strength": "Powerful magic user, vast knowledge of celestial lore, excellent teacher", 58 | "weakness": "Can be cryptic and difficult to understand at times, limited physical mobility", 59 | "flaw": "Holds magic in high regard, possibly hesitant to trust humans fully", 60 | "motivation": "Seeks to maintain the balance between the human world and the magical realm, desires to pass on her knowledge to a worthy successor", 61 | "other": "" 62 | }, 63 | { 64 | "id": "ec7f5de0-aa19-421f-812c-77a286737214", 65 | "location": { 66 | "x": 1175, 67 | "y": 616 68 | }, 69 | "type": "Character", 70 | "name": "Akira Sato", 71 | "color": "#00ffff", 72 | "imageSrc": "", 73 | "personality": "Outgoing, enthusiastic, always has a joke or story to tell", 74 | "quirk": "Trips over his own feet frequently, has a knack for getting into trouble (often unintentionally)", 75 | "like": "Spending time with Hanako, trying new foods, participating in local festivals", 76 | "dislike": "Boredom, loneliness, seeing his friends upset", 77 | "strength": "Loyal, supportive, brings out the lighter side in Hanako", 78 | "weakness": "Can be oblivious to social cues, sometimes lacks focus", 79 | "flaw": "Can be a bit clingy and overprotective of Hanako", 80 | "motivation": "Secretly harbors a deeper affection for Hanako, wants to be there for her no matter what, even if it means helping her with her magical battles (despite not knowing the full extent of them)", 81 | "other": "" 82 | }, 83 | { 84 | "id": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 85 | "location": { 86 | "x": 3644, 87 | "y": 88 88 | }, 89 | "type": "Character", 90 | "name": "Yami-D", 91 | "color": "#808000", 92 | "imageSrc": "", 93 | "personality": "Malicious, manipulative, feeds on the weaknesses and desires of others.", 94 | "quirk": "Speaks in glitching fragments of code and advertisements, enjoys toying with its victims before consuming them.", 95 | "like": "Feeding on negative emotions, spreading chaos and despair, corrupting dreams.", 96 | "dislike": "Purity, genuine happiness, acts of selflessness that disrupt its control.", 97 | "strength": "Powerful digital manipulation, can create hypnotic illusions and advertisements, possesses vast knowledge of consumer desires.", 98 | "weakness": "Vulnerable to pure celestial energy, can be disrupted by strong emotions like love and hope. Reliant on technology - a power outage or EMP could be disastrous.", 99 | "flaw": "Overconfident, underestimates the power of human connection and genuine desire.", 100 | "motivation": "Consumes dreams to fuel its own power and existence. Believes humans are weak and easily manipulated by their desires. Wants to control the world by turning everyone's dreams into a twisted reflection of their materialistic wants.", 101 | "other": "" 102 | }, 103 | { 104 | "id": "122ee6a4-0e6f-4822-abd8-60c509ad579d", 105 | "location": { 106 | "x": 1835, 107 | "y": 1092 108 | }, 109 | "type": "Location", 110 | "name": "Sakura High School", 111 | "color": "#008040", 112 | "imageSrc": "", 113 | "description": "By day, Sakura High hides its secret as a training ground for magical girls, its classrooms doubling as enchantment chambers under the glow of cherry blossom trees." 114 | }, 115 | { 116 | "id": "6427a20e-226d-4df6-8f12-b4ec82c192c2", 117 | "location": { 118 | "x": 3172, 119 | "y": 615 120 | }, 121 | "type": "Organization", 122 | "name": "Glitching Horde", 123 | "color": "#400000", 124 | "objective": "Seeks to infect the world with corrupted desires, turning humanity into mindless consumers trapped in a digital nightmare.", 125 | "detail": "Yami-D's scattered followers, the Glitching Horde, spread like a digital virus, hijacking dreams and desires through corrupted internet connections." 126 | }, 127 | { 128 | "id": "02d3adf1-5907-4a05-9b8f-37c1e36fe20e", 129 | "location": { 130 | "x": 3214, 131 | "y": 329 132 | }, 133 | "type": "Location", 134 | "name": "Yami-D's lair", 135 | "color": "#804000", 136 | "imageSrc": "", 137 | "description": "Atop a skyscraper shaped like a distorted smartphone screen, Yami-D's lair pulsed with hypnotic advertisements, bleeding digital nightmares into the Tokyo night." 138 | }, 139 | { 140 | "id": "dab3851a-e0f1-4185-b905-c7962780ed1f", 141 | "location": { 142 | "x": 1651, 143 | "y": 458 144 | }, 145 | "type": "Organization", 146 | "name": "Dream Weavers", 147 | "color": "#00ff80", 148 | "objective": "Bound by the power of the stars, fight to protect humanity's dreams from the digital corruption of Yami-D and the Glitching Horde.", 149 | "detail": "A network of young women who use celestial magic to safeguard dreams from the clutches of digital nightmares." 150 | }, 151 | { 152 | "id": "5a04aa04-d648-4882-9296-b5a8571d223c", 153 | "location": { 154 | "x": 1395, 155 | "y": 55 156 | }, 157 | "type": "Location", 158 | "name": "Star Tea House", 159 | "color": "#ffff00", 160 | "imageSrc": "", 161 | "description": "Disguised as a charming, traditional tea house, the Hoshi Chaya (Star Tea House) serves as a meeting point for the Dream Weavers. Beneath the fragrant steam and delicate teacups, they strategize and share information." 162 | }, 163 | { 164 | "id": "b503d84e-67e5-4448-9f03-5523ccd9c104", 165 | "location": { 166 | "x": 2823, 167 | "y": 89 168 | }, 169 | "type": "Story", 170 | "name": "Season 1", 171 | "color": "#FFFFFF", 172 | "description": "In modern Tokyo, bubbly high school student Hanako leads a double life. By day, she serves sugary treats at a maid cafe. By night, she transforms into Hoshizora, a magical girl who joins the Dream Weavers, a hidden network protecting humanity's dreams from the nightmarish digital corruption spread by Yami-D and its Glitching Horde." 173 | }, 174 | { 175 | "id": "45c3cd76-5c96-4a02-84ee-036e8d7bdb66", 176 | "location": { 177 | "x": 2682, 178 | "y": 837 179 | }, 180 | "type": "Lore", 181 | "name": "Hoshizora", 182 | "color": "#ff00ff", 183 | "detail": "Hoshizora isn't just a magical girl persona; it's a title and a legacy. Passed down through generations of Dream Weavers, Hoshizora signifies the protector who wields the power of the stars. By day, Hanako might be an ordinary student, but under the moonlight, she transforms, channeling the celestial energy to become the newest Hoshizora, the Star Weaver." 184 | }, 185 | { 186 | "id": "4bd611a5-c114-41b8-b156-e85c3b82010a", 187 | "location": { 188 | "x": 163, 189 | "y": 842 190 | }, 191 | "type": "Lore", 192 | "name": "Dream Weaver Magic", 193 | "color": "#0080c0", 194 | "detail": "Source: Celestial Energy (stars & constellations)\nFuel: Positive Emotions (hope, courage)\nTransformation: Personal Item (imbued with celestial energy) - e.g., Hanako's hair clip\nAbilities:\n- Defense: Shimmering curtains of starlight to block nightmares and attacks\n- Offense: Celestial blasts or constellation-inspired attacks (e.g., Starlight Serenade)\n- Dream Navigation: Enter dreamscapes to fight nightmares directly\n\nLimitations:\n- Negative Emotions weaken magic\n- Limited Power for young Dream Weavers\n- Weak Celestial Connection hinders abilities (e.g., heavy clouds)" 195 | }, 196 | { 197 | "id": "5fcf2528-599c-4330-8b69-30f3dd0e3067", 198 | "location": { 199 | "x": 4257, 200 | "y": 185 201 | }, 202 | "type": "Lore", 203 | "name": "Yami-D's Digital Corruption", 204 | "color": "#400080", 205 | "detail": "Source: Digital Manipulation\nPower:\n- Hypnotic Advertisements: Creates captivating ads that manipulate desires and trap minds in a digital dream world.\n- Corrupted Code Tendrils: Lashes out with corrupted code to physically restrain and harm opponents.\n- Dream Infiltration: Can access and distort human dreams, feeding on negativity and amplifying desires.\n\nWeakness:\n- Pure Celestial Energy: Disrupted by powerful displays of starlight magic used by the Dream Weavers.\n- Technology Reliance: Vulnerable to disruptions in its digital infrastructure (e.g., EMP attack).\n- Overconfidence: Underestimates the power of human connection and genuine desires." 206 | }, 207 | { 208 | "id": "f0e625ce-41fb-4fa8-bcf8-8a2a121de151", 209 | "location": { 210 | "x": 3190, 211 | "y": 60 212 | }, 213 | "type": "Event", 214 | "name": "Witnessing Evil", 215 | "color": "#FFFFFF", 216 | "detail": "Hanako witnesses Yami-D's corrupted advertisements manipulating people in Shibuya Crossing." 217 | }, 218 | { 219 | "id": "570fbc1a-8954-4054-9b30-48615acd3864", 220 | "location": { 221 | "x": 2322, 222 | "y": 1090 223 | }, 224 | "type": "Event", 225 | "name": "Confrontation", 226 | "color": "#FFFFFF", 227 | "detail": "As Hoshizora, she confronts Yami-D in a battle across the neon-lit rooftops of Tokyo." 228 | }, 229 | { 230 | "id": "4c0c1746-5fd3-40fa-a70c-1c5396b55f12", 231 | "location": { 232 | "x": 2339, 233 | "y": 160 234 | }, 235 | "type": "Event", 236 | "name": "Battle Assist", 237 | "color": "#FFFFFF", 238 | "detail": "While battling, Hoshizora encounters another Dream Weaver (potentially Yuuri or a new character) who assists her." 239 | }, 240 | { 241 | "id": "5b720633-f29d-46fb-9f82-61161962401b", 242 | "location": { 243 | "x": 2494, 244 | "y": 465 245 | }, 246 | "type": "Event", 247 | "name": "Worries", 248 | "color": "#FFFFFF", 249 | "detail": "Back in her normal life, Hanako ponders the growing threat of Yami-D and the responsibility of being Hoshizora." 250 | }, 251 | { 252 | "id": "bf35b66e-10a8-4158-813b-7e632f9b0cdd", 253 | "location": { 254 | "x": 1823, 255 | "y": 96 256 | }, 257 | "type": "Event", 258 | "name": "Mentoring", 259 | "color": "#FFFFFF", 260 | "detail": "Hanako seeks guidance from her mentor Hoshihikari to learn more about Yami-D and her powers." 261 | }, 262 | { 263 | "id": "9dd9473a-44a7-42fb-8ce7-d1dcf1d88d81", 264 | "location": { 265 | "x": 2814, 266 | "y": 595 267 | }, 268 | "type": "Event", 269 | "name": "Double Life", 270 | "color": "#FFFFFF", 271 | "detail": "Hanako's double life becomes more complicated as she juggles school, her part-time job, and her duties as Hoshizora." 272 | } 273 | ], 274 | "links": [ 275 | { 276 | "nodeFromId": "5a04aa04-d648-4882-9296-b5a8571d223c", 277 | "nodeToId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0" 278 | }, 279 | { 280 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 281 | "nodeToId": "5a04aa04-d648-4882-9296-b5a8571d223c" 282 | }, 283 | { 284 | "nodeFromId": "4bd611a5-c114-41b8-b156-e85c3b82010a", 285 | "nodeToId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693" 286 | }, 287 | { 288 | "nodeFromId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0", 289 | "nodeToId": "4bd611a5-c114-41b8-b156-e85c3b82010a" 290 | }, 291 | { 292 | "nodeFromId": "4bd611a5-c114-41b8-b156-e85c3b82010a", 293 | "nodeToId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be" 294 | }, 295 | { 296 | "nodeFromId": "5a04aa04-d648-4882-9296-b5a8571d223c", 297 | "nodeToId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be" 298 | }, 299 | { 300 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 301 | "nodeToId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be" 302 | }, 303 | { 304 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 305 | "nodeToId": "45c3cd76-5c96-4a02-84ee-036e8d7bdb66" 306 | }, 307 | { 308 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 309 | "nodeToId": "122ee6a4-0e6f-4822-abd8-60c509ad579d" 310 | }, 311 | { 312 | "nodeFromId": "122ee6a4-0e6f-4822-abd8-60c509ad579d", 313 | "nodeToId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0" 314 | }, 315 | { 316 | "nodeFromId": "ec7f5de0-aa19-421f-812c-77a286737214", 317 | "nodeToId": "122ee6a4-0e6f-4822-abd8-60c509ad579d" 318 | }, 319 | { 320 | "nodeFromId": "5a04aa04-d648-4882-9296-b5a8571d223c", 321 | "nodeToId": "dab3851a-e0f1-4185-b905-c7962780ed1f" 322 | }, 323 | { 324 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 325 | "nodeToId": "dab3851a-e0f1-4185-b905-c7962780ed1f" 326 | }, 327 | { 328 | "nodeFromId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be", 329 | "nodeToId": "dab3851a-e0f1-4185-b905-c7962780ed1f" 330 | }, 331 | { 332 | "nodeFromId": "dab3851a-e0f1-4185-b905-c7962780ed1f", 333 | "nodeToId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0" 334 | }, 335 | { 336 | "nodeFromId": "02d3adf1-5907-4a05-9b8f-37c1e36fe20e", 337 | "nodeToId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db" 338 | }, 339 | { 340 | "nodeFromId": "02d3adf1-5907-4a05-9b8f-37c1e36fe20e", 341 | "nodeToId": "6427a20e-226d-4df6-8f12-b4ec82c192c2" 342 | }, 343 | { 344 | "nodeFromId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 345 | "nodeToId": "6427a20e-226d-4df6-8f12-b4ec82c192c2" 346 | }, 347 | { 348 | "nodeFromId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 349 | "nodeToId": "5fcf2528-599c-4330-8b69-30f3dd0e3067" 350 | }, 351 | { 352 | "nodeFromId": "ff923a1c-50bb-4ee7-9bc2-9c9fcedb60f0", 353 | "nodeToId": "4c0c1746-5fd3-40fa-a70c-1c5396b55f12" 354 | }, 355 | { 356 | "nodeFromId": "4c0c1746-5fd3-40fa-a70c-1c5396b55f12", 357 | "nodeToId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693" 358 | }, 359 | { 360 | "nodeFromId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 361 | "nodeToId": "570fbc1a-8954-4054-9b30-48615acd3864" 362 | }, 363 | { 364 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 365 | "nodeToId": "570fbc1a-8954-4054-9b30-48615acd3864" 366 | }, 367 | { 368 | "nodeFromId": "6aa7369b-d01c-4e41-a07d-3ac14ae828db", 369 | "nodeToId": "f0e625ce-41fb-4fa8-bcf8-8a2a121de151" 370 | }, 371 | { 372 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 373 | "nodeToId": "f0e625ce-41fb-4fa8-bcf8-8a2a121de151" 374 | }, 375 | { 376 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 377 | "nodeToId": "5b720633-f29d-46fb-9f82-61161962401b" 378 | }, 379 | { 380 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 381 | "nodeToId": "9dd9473a-44a7-42fb-8ce7-d1dcf1d88d81" 382 | }, 383 | { 384 | "nodeFromId": "6d9a8af6-2f25-4af7-ae6a-ff9bf38d02be", 385 | "nodeToId": "bf35b66e-10a8-4158-813b-7e632f9b0cdd" 386 | }, 387 | { 388 | "nodeFromId": "24ec3ea7-81c2-4d42-8016-3c6d8d37b693", 389 | "nodeToId": "bf35b66e-10a8-4158-813b-7e632f9b0cdd" 390 | }, 391 | { 392 | "nodeFromId": "b503d84e-67e5-4448-9f03-5523ccd9c104", 393 | "nodeToId": "bf35b66e-10a8-4158-813b-7e632f9b0cdd" 394 | }, 395 | { 396 | "nodeFromId": "f0e625ce-41fb-4fa8-bcf8-8a2a121de151", 397 | "nodeToId": "b503d84e-67e5-4448-9f03-5523ccd9c104" 398 | }, 399 | { 400 | "nodeFromId": "b503d84e-67e5-4448-9f03-5523ccd9c104", 401 | "nodeToId": "570fbc1a-8954-4054-9b30-48615acd3864" 402 | }, 403 | { 404 | "nodeFromId": "5b720633-f29d-46fb-9f82-61161962401b", 405 | "nodeToId": "b503d84e-67e5-4448-9f03-5523ccd9c104" 406 | }, 407 | { 408 | "nodeFromId": "b503d84e-67e5-4448-9f03-5523ccd9c104", 409 | "nodeToId": "9dd9473a-44a7-42fb-8ce7-d1dcf1d88d81" 410 | }, 411 | { 412 | "nodeFromId": "4c0c1746-5fd3-40fa-a70c-1c5396b55f12", 413 | "nodeToId": "b503d84e-67e5-4448-9f03-5523ccd9c104" 414 | } 415 | ] 416 | } -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef 4 | const eslint = require('@eslint/js'); 5 | // eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef 6 | const tseslint = require('typescript-eslint'); 7 | // eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef 8 | const eslintPluginPrettierRecommended = require('eslint-plugin-prettier/recommended'); 9 | 10 | // eslint-disable-next-line no-undef 11 | module.exports = [ 12 | eslint.configs.recommended, 13 | ...tseslint.configs.recommended, 14 | eslintPluginPrettierRecommended, 15 | { 16 | ignores: ['build/*'], 17 | }, 18 | ]; 19 | -------------------------------------------------------------------------------- /images/splash1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/images/splash1.png -------------------------------------------------------------------------------- /images/splash2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/images/splash2.png -------------------------------------------------------------------------------- /img/asc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/asc.gif -------------------------------------------------------------------------------- /img/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/bg.gif -------------------------------------------------------------------------------- /img/conv30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/conv30.png -------------------------------------------------------------------------------- /img/conv40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/conv40.png -------------------------------------------------------------------------------- /img/conv50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/conv50.png -------------------------------------------------------------------------------- /img/desc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/desc.gif -------------------------------------------------------------------------------- /img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /img/heart30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/heart30.png -------------------------------------------------------------------------------- /img/heart40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/heart40.png -------------------------------------------------------------------------------- /img/heart50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/heart50.png -------------------------------------------------------------------------------- /img/lastfm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/lastfm.gif -------------------------------------------------------------------------------- /img/m1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/m1.png -------------------------------------------------------------------------------- /img/m2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/m2.png -------------------------------------------------------------------------------- /img/m3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/m3.png -------------------------------------------------------------------------------- /img/m4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/m4.png -------------------------------------------------------------------------------- /img/m5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/m5.png -------------------------------------------------------------------------------- /img/people35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/people35.png -------------------------------------------------------------------------------- /img/people45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/people45.png -------------------------------------------------------------------------------- /img/people55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/people55.png -------------------------------------------------------------------------------- /img/pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/pin.png -------------------------------------------------------------------------------- /img/songkick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/json574/commune-events-scrap/7635dc41e6fb3e773920df4a5475e15f0217de9b/img/songkick.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 40 | 41 | 42 | 43 | 44 | 45 | 58 | 59 | 60 | 82 | 83 |
84 |
85 | 86 | 87 | 88 | 89 | 90 | 91 | Weekend

92 | 93 | 94 |
95 | 96 |
97 |
98 | 99 |
100 |
101 | 102 |
103 | No events are matching this filter. 104 |
105 | 106 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /js/eventslist.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Stores a list of events, also allows to filter them. Each event is an object 3 | * with the following fields 4 | * 5 | * artist : string 6 | * type : Concert/Festival 7 | * startDate : Date 8 | * location : {lat, lng} 9 | * venue : string 10 | * city: string 11 | * country : string 12 | * tags : [] string 13 | **/ 14 | function EventsList() { 15 | this.events = []; 16 | } 17 | 18 | /** 19 | * Adds an event to the event list. It transforms it from the songkick format 20 | * to internal format, that stores only the fields that are used. 21 | **/ 22 | EventsList.prototype.addEvent = function(songkickArtist, songkickEvent) { 23 | var eventCity = songkickEvent.location ? songkickEvent.location.city : ""; 24 | var lastComma = eventCity.lastIndexOf(","); 25 | 26 | var city = $.trim(eventCity.substring(0, lastComma)); 27 | var country = $.trim(eventCity.substring(lastComma + 1)); 28 | 29 | var event = { 30 | artist : songkickArtist.displayName, 31 | location : { 32 | lat : songkickEvent.location ? songkickEvent.location.lat : 0, 33 | lng : songkickEvent.location ? songkickEvent.location.lng : 0 34 | }, 35 | venue : songkickEvent.venue ? songkickEvent.venue.displayName : "", 36 | type : songkickEvent.type, 37 | city : city, 38 | country : country, 39 | startDate : new Date(songkickEvent.start ? songkickEvent.start.date : Date.now()), 40 | tags: songkickArtist.tags, 41 | url: { 42 | songkick: songkickEvent.uri 43 | } 44 | } 45 | 46 | this.events.push(event); 47 | return event; 48 | } 49 | 50 | /** 51 | * Gets a list of suggestions that can be used ina typeahead for the added 52 | * events. 53 | */ 54 | EventsList.prototype.getSuggestions = function() { 55 | var suggestions = {}; 56 | 57 | util.each(this.events, function(event) { 58 | util.eachValue(event, function(value) { 59 | if (util.is_string(value)) { 60 | suggestions[value] = 1; 61 | } 62 | }) 63 | }); 64 | 65 | return util.keys(suggestions); 66 | } 67 | 68 | /** 69 | * Gets all events in the event list. 70 | */ 71 | EventsList.prototype.getEvents = function() { 72 | return this.events; 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /js/eventsmap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the map. Events can be added to it, and it can be cleared. 3 | */ 4 | function EventsMap() { 5 | var mapOptions = { 6 | center: new google.maps.LatLng(39.325178, 13.359375), 7 | zoom: 2, 8 | mapTypeId: google.maps.MapTypeId.ROADMAP, 9 | mapTypeControlOptions : { 10 | position: google.maps.ControlPosition.TOP_RIGHT 11 | }, 12 | panControlOptions: { 13 | position: google.maps.ControlPosition.RIGHT_TOP 14 | }, 15 | zoomControlOptions: { 16 | position: google.maps.ControlPosition.RIGHT_TOP 17 | }, 18 | streetViewControlOptions: { 19 | position: google.maps.ControlPosition.RIGHT_TOP 20 | } 21 | }; 22 | 23 | this.infoWindowCount = 0; // used for generating unique id for each infowindow 24 | this.map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions); 25 | this.clusterer = new MarkerClusterer(this.map, [], {minimumClusterSize:1, zoomOnClick:false}); 26 | this.infoWindow = new google.maps.InfoWindow(); 27 | 28 | google.maps.event.addListener(this.clusterer, 'clusterclick', $.proxy(this.showInfoWindow, this)); 29 | } 30 | 31 | /** 32 | * Adds a marker with the event to the google map. 33 | **/ 34 | EventsMap.prototype.addEvent = function(event) { 35 | var location = new google.maps.LatLng(event.location.lat, event.location.lng); 36 | var marker = new google.maps.Marker({ 37 | position: location, 38 | map: this.map, 39 | title: event.name 40 | }); 41 | 42 | marker.event = event; 43 | 44 | this.clusterer.addMarker(marker); 45 | } 46 | 47 | /** 48 | * Adds all events to the event map. 49 | */ 50 | EventsMap.prototype.addEvents = function(events) { 51 | util.each(events, $.proxy(this.addEvent, this)); 52 | } 53 | 54 | /** 55 | * Clears all event markers. 56 | */ 57 | EventsMap.prototype.clear = function() { 58 | this.clusterer.clearMarkers(); 59 | } 60 | 61 | /** 62 | * Shows an InfoWindow with the information for all events in a cluster. 63 | */ 64 | EventsMap.prototype.showInfoWindow = function(cluster) { 65 | var table = new TableBuilder(["Date", "Artist", "Venue", "City", "Country"], 'tablesorter'); 66 | 67 | var markers = cluster.getMarkers(); 68 | for (var i = 0; i < markers.length; i++) { 69 | var event = markers[i].event; 70 | var d = event.startDate; 71 | var dateString = ("0"+(d.getMonth()+1)).slice(-2) + "/" + ("0" + d.getDate()).slice(-2) + "/" + d.getFullYear(); 72 | table.addRow([dateString, "" + event.artist + "", event.venue, event.city, event.country]); 73 | } 74 | 75 | this.infoWindow.setContent('
' + table.build() + "
"); 76 | // put the info window at a bogus marker 77 | var center = {lat: cluster.getCenter().lat(), lng: cluster.getCenter().lng()}; 78 | var image = { 79 | url: 'https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png', 80 | size: new google.maps.Size(0, 0), 81 | origin: new google.maps.Point(0, 0), 82 | anchor: new google.maps.Point(0, 0) 83 | }; 84 | this.infoWindow.open(this.map, new google.maps.Marker({position: center, map: this.map, icon: image})); 85 | $('.tablesorter').tablesorter(); 86 | } -------------------------------------------------------------------------------- /js/filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents teh filter dialogue. It can can show it, and match events agains it. 3 | */ 4 | function Filter(eventList) { 5 | this.fromDate = $("#from-date"); 6 | this.toDate = $("#to-date"); 7 | this.weekend = $("#weekend"); 8 | this.filter = $("#filter-text"); 9 | this.filterDiv = $("#filter-div"); 10 | 11 | util.each([this.fromDate, this.toDate, this.filter], function(element) { 12 | element.val(""); 13 | }); 14 | 15 | this.fromDate.datepicker(); 16 | this.toDate.datepicker(); 17 | this.filterDiv.css('display', 'none'); 18 | } 19 | 20 | Filter.prototype.fromDateFilter = function(event) { 21 | return this.fromDate.val() ? new Date(this.fromDate.val()) <= event.startDate : true; 22 | } 23 | 24 | Filter.prototype.toDateFilter = function(event) { 25 | return this.toDate.val() ? new Date(this.toDate.val()) >= event.startDate : true; 26 | } 27 | 28 | Filter.prototype.weekendFilter = function(event) { 29 | var day = event.startDate.getDay(); 30 | return this.weekend.is(':checked') ? (day == 5 || day == 6) : true; 31 | } 32 | 33 | Filter.prototype.stringMatchFilter = function(event) { 34 | var match = this.filter.val().toLowerCase(); 35 | 36 | function matches(value) { 37 | return (util.is_string(value)) ? (value.toLowerCase().indexOf(match) != -1) : false; 38 | } 39 | 40 | return match ? util.or(util.values(event), matches) : true; 41 | } 42 | 43 | /** 44 | * Shows the filter menu. 45 | */ 46 | Filter.prototype.show = function(eventsList) { 47 | this.filterDiv.show(); 48 | var suggestions = eventsList.getSuggestions(); 49 | this.filter.typeahead(); 50 | // the source is set here, so it can be updated 51 | this.filter.data('typeahead').source = suggestions; 52 | } 53 | 54 | /** 55 | * Checks if event is matching all filters. 56 | */ 57 | Filter.prototype.isMatching = function(event) { 58 | var filters = [$.proxy(this.fromDateFilter, this), 59 | $.proxy(this.toDateFilter, this), 60 | $.proxy(this.weekendFilter, this), 61 | $.proxy(this.stringMatchFilter, this)]; 62 | 63 | return util.and(filters, function(filter) { 64 | var result = filter(event); 65 | return result; 66 | }); 67 | } 68 | -------------------------------------------------------------------------------- /js/lastfm.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Wrapper around the Last.FM API. 3 | */ 4 | function LastFM() { 5 | this.apiKey = "26fd5c4e94f30e7a0f2489b2c5babb61"; 6 | } 7 | 8 | /** 9 | * Gets the 5 most popular tags for an artist. 10 | */ 11 | LastFM.prototype.getTags = function(artist, callback) { 12 | var url = "http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&artist=" + artist + "&api_key=" + this.apiKey + "&format=json&callback=?"; 13 | 14 | var handler = function(response) { 15 | var tags = []; 16 | 17 | if (response && response.toptags && response.toptags.tag) { 18 | var topTags = response.toptags.tag; 19 | var length = Math.min(5, topTags.length); 20 | for (i = 0; i < length; i++) { 21 | tags.push(topTags[i].name); 22 | } 23 | } 24 | 25 | callback(tags); 26 | } 27 | 28 | $.ajax({ 29 | url: url, 30 | dataType: 'json', 31 | success: handler, 32 | error: function() { callback([]); } 33 | }); 34 | } -------------------------------------------------------------------------------- /js/songkick.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Wrapper around the songkick api. 3 | */ 4 | function Songkick(user, eventsList, eventsMap) { 5 | this.apiKey = "hZ2Fewy4geaBhLCS"; 6 | this.user = user; 7 | this.eventsList = eventsList; 8 | this.eventsMap = eventsMap; 9 | this.events = []; 10 | this.lastfm = new LastFM(); 11 | } 12 | 13 | /** 14 | * Displays all future events for the tracked artists. 15 | */ 16 | Songkick.prototype.showEventsForTrackerArtists = function(onFinish) { 17 | var trackingsUrl = "http://api.songkick.com/api/3.0/users/" + this.user +"/artists/tracked.json?location=clientip&apikey=" + this.apiKey + "&jsoncallback=?"; 18 | var status = new Status(onFinish); 19 | 20 | function initializeStatus(firstPage) { 21 | status.setTotal(firstPage.resultsPage.totalEntries); 22 | } 23 | 24 | function addEvent(songkickArtist) { 25 | return function(songkickEvent) { 26 | var event = this.eventsList.addEvent(songkickArtist, songkickEvent); 27 | this.eventsMap.addEvent(event); 28 | } 29 | } 30 | 31 | function updateStatus(artist) { 32 | return function() { 33 | status.increment(artist.displayName); 34 | } 35 | } 36 | 37 | function showEvents(artist) { 38 | if (artist.onTourUntil != null) { 39 | this.lastfm.getTags(artist.displayName, $.proxy(function(tags) { 40 | artist.tags = tags; 41 | var eventsUrl = "http://api.songkick.com/api/3.0/artists/" + artist.id + "/calendar.json?apikey=" + this.apiKey + "&jsoncallback=?"; 42 | this.forEachItem({ url:eventsUrl, processItem:addEvent(artist), onFinish:updateStatus(artist) }); 43 | }, this)); 44 | } else { 45 | updateStatus(artist)(); 46 | } 47 | } 48 | 49 | this.forEachItem({url:trackingsUrl, processItem:showEvents, onStart:initializeStatus, hide: function() { status.finish() } }); 50 | } 51 | 52 | /** 53 | * Iterates through paginated resutls and calls processItem for each result. 54 | */ 55 | Songkick.prototype.forEachItem = function(params) { 56 | var processItem = $.proxy(params.processItem, this); 57 | var onStart = $.proxy(params.onStart || function(){}, this); 58 | var onFinish = $.proxy(params.onFinish || function(){}, this); 59 | 60 | var totalPages; 61 | var processedPages = 0; 62 | 63 | function processPage(data) { 64 | var results = util.getFirstProperty(data.resultsPage.results); 65 | util.each(results, processItem); 66 | 67 | if (++processedPages == totalPages) { 68 | onFinish(); 69 | } 70 | } 71 | 72 | function forEachPage(firstPage) { 73 | totalPages = Math.ceil(firstPage.resultsPage.totalEntries / firstPage.resultsPage.perPage); 74 | 75 | onStart(firstPage); 76 | 77 | processPage(firstPage); 78 | for (var page = 2; page <= totalPages; page++) { 79 | $.getJSON(params.url + "&page=" + page, processPage).fail(function(e) { 80 | params.hide(); 81 | }); 82 | } 83 | } 84 | 85 | $.getJSON(params.url, forEachPage).fail(function(e) { 86 | console.log(e); 87 | params.hide(); 88 | }); 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /js/status.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Status modal. It displays a progress bar which is updated on every increment 3 | * call. total is the number of increment calls expected and onFinish is an 4 | * optional function that should be called when the status has reached 100%. 5 | **/ 6 | function Status(onFinish) { 7 | onFinish = onFinish || function() {}; 8 | this.processed = 0; 9 | this.finish = function () { 10 | $('#status-modal').hide(); 11 | onFinish(); 12 | } 13 | 14 | $("#status-modal").modal({ show:true, keyboard:false, backdrop:false }); 15 | $("#status-modal").show(); 16 | $("#progress-bar").css("width", "0%"); 17 | } 18 | 19 | /** 20 | * Sets the total number of increments expected. 21 | */ 22 | Status.prototype.setTotal = function(total) { 23 | this.total = total; 24 | } 25 | 26 | /** 27 | * Increments the progress bar and displays the info text. 28 | **/ 29 | Status.prototype.increment = function(info) { 30 | this.processed++; 31 | 32 | if (this.processed / this.total * 100 > 90 && this.processed < this.total) { 33 | window.clearTimeout(this.timeout); 34 | this.timeout = window.setTimeout($.proxy(this.finish, this), 2000) 35 | } 36 | 37 | $("#progress-bar").css("width", Math.floor( (this.processed / this.total) * 100 ) + "%"); 38 | $("#progress-info").html(info); 39 | 40 | if (this.processed == this.total) { 41 | setTimeout($.proxy(this.finish, this), 500); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /js/ui.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Initializes the document. 3 | */ 4 | $(document).ready(function() { 5 | var eventsMap = new EventsMap(); 6 | initializeSearchBox(eventsMap); 7 | }) 8 | 9 | /** 10 | * Initializes the search box. 11 | **/ 12 | function initializeSearchBox(eventsMap) { 13 | $("#search-button").click(function() { 14 | window.location.hash = $("#search-box").val(); 15 | $("#search-button").addClass("disabled"); 16 | $("#search-box").attr("disabled", ""); 17 | $("#search-box").blur(); 18 | $("#no-results-alert").css("display", "none"); 19 | eventsMap.clear(); 20 | 21 | var eventsList = new EventsList(); 22 | var filter = new Filter(); 23 | var songkick = new Songkick($("#search-box").val(), eventsList, eventsMap); 24 | 25 | songkick.showEventsForTrackerArtists(function() { 26 | $("#search-button").removeClass("disabled"); 27 | $("#search-box").removeAttr("disabled"); 28 | filter.show(eventsList); 29 | }); 30 | 31 | $("#filter-button").click(function() { 32 | var matchingEvents = eventsList.getEvents().filter($.proxy(filter.isMatching, filter)); 33 | eventsMap.clear(); 34 | if (matchingEvents.length == 0) { 35 | $("#no-results-alert").css("display", "block") 36 | } else { 37 | $("#no-results-alert").css("display", "none"); 38 | eventsMap.addEvents(matchingEvents); 39 | } 40 | return false; 41 | }); 42 | 43 | return false; 44 | }); 45 | 46 | $("#search-box").keydown(function(event){ 47 | if(event.keyCode == 13){ 48 | $("#search-button").click(); 49 | } 50 | }); 51 | 52 | var hash = window.location.hash.slice(1); 53 | 54 | if (hash) { 55 | $("#search-box").val(hash); 56 | $("#search-button").click(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /js/util.js: -------------------------------------------------------------------------------- 1 | var util = {} 2 | 3 | /** 4 | * Gets the first property of an object. 5 | */ 6 | util.getFirstProperty = function(object) { 7 | var firstProperty = {}; 8 | for (var property in object) { 9 | firstProperty = object[property]; 10 | break; 11 | } 12 | return firstProperty; 13 | } 14 | 15 | /** 16 | * Calls processItem on item, or if item is a list it calls it for each element 17 | * in the list. 18 | */ 19 | util.each = function(item, processItem) { 20 | if ($.isArray(item)) { 21 | $.each(item, function(index, value) { 22 | processItem(value); 23 | }); 24 | } else { 25 | processItem(item); 26 | } 27 | } 28 | 29 | /** 30 | * Calls the processValue function for each value in a hash. 31 | **/ 32 | util.eachValue = function(hash, processValue) { 33 | for (var key in hash) { 34 | util.each(hash[key], processValue); 35 | } 36 | } 37 | 38 | /** 39 | * Returns a list with the values in the hash. 40 | */ 41 | util.values = function(hash) { 42 | var values = []; 43 | util.eachValue(hash, $.proxy(values.push, values)); 44 | return values; 45 | } 46 | 47 | /** 48 | * Returns a list with the keys in the hash. 49 | */ 50 | util.keys = function(hash) { 51 | var keys = []; 52 | for (var key in hash) { 53 | keys.push(key); 54 | } 55 | return keys; 56 | } 57 | 58 | /** 59 | * Returns true if predicate is true for all items. 60 | **/ 61 | util.and = function(items, predicate) { 62 | var result = true; 63 | util.each(items, function(item) { 64 | result = result && predicate(item); 65 | }); 66 | 67 | return result; 68 | } 69 | 70 | /** 71 | * Returns true if predicate is true for some of the items. 72 | */ 73 | util.or = function(items, predicate) { 74 | var result = false; 75 | util.each(items, function(item) { 76 | result = result || predicate(item); 77 | }); 78 | 79 | return result; 80 | } 81 | 82 | /** 83 | * Checks if the input is string. 84 | **/ 85 | util.is_string = function(input) { 86 | return $.type(input) === 'string'; 87 | } 88 | 89 | /** 90 | * Class that facilitates building the html for a table. 91 | */ 92 | function TableBuilder(columns, optionalClass) { 93 | optionalClass = optionalClass || ""; 94 | this.html = ''; 95 | this.html += ''; 96 | for (var i = 0; i < columns.length; i++) { 97 | columns[i] += '    '; 98 | } 99 | this._addRow(columns, 'th'); 100 | this.html += ''; 101 | } 102 | 103 | TableBuilder.prototype._addRow = function(values, columnTag) { 104 | this.html += ''; 105 | for (var i = 0; i < values.length; i++) { 106 | this.html += '<' + columnTag + '>' + values[i] + ''; 107 | } 108 | this.html += ''; 109 | } 110 | 111 | TableBuilder.prototype.addRow = function(values) { 112 | this._addRow(values, 'td'); 113 | } 114 | 115 | TableBuilder.prototype.build = function() { 116 | this.html += "
"; 117 | return this.html; 118 | } -------------------------------------------------------------------------------- /lib/bootstrap-alert.js: -------------------------------------------------------------------------------- 1 | /* ========================================================== 2 | * bootstrap-alert.js v2.0.1 3 | * http://twitter.github.com/bootstrap/javascript.html#alerts 4 | * ========================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function( $ ){ 22 | 23 | "use strict" 24 | 25 | /* ALERT CLASS DEFINITION 26 | * ====================== */ 27 | 28 | var dismiss = '[data-dismiss="alert"]' 29 | , Alert = function ( el ) { 30 | $(el).on('click', dismiss, this.close) 31 | } 32 | 33 | Alert.prototype = { 34 | 35 | constructor: Alert 36 | 37 | , close: function ( e ) { 38 | var $this = $(this) 39 | , selector = $this.attr('data-target') 40 | , $parent 41 | 42 | if (!selector) { 43 | selector = $this.attr('href') 44 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 45 | } 46 | 47 | $parent = $(selector) 48 | $parent.trigger('close') 49 | 50 | e && e.preventDefault() 51 | 52 | $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) 53 | 54 | $parent 55 | .trigger('close') 56 | .removeClass('in') 57 | 58 | function removeElement() { 59 | $parent 60 | .trigger('closed') 61 | .remove() 62 | } 63 | 64 | $.support.transition && $parent.hasClass('fade') ? 65 | $parent.on($.support.transition.end, removeElement) : 66 | removeElement() 67 | } 68 | 69 | } 70 | 71 | 72 | /* ALERT PLUGIN DEFINITION 73 | * ======================= */ 74 | 75 | $.fn.alert = function ( option ) { 76 | return this.each(function () { 77 | var $this = $(this) 78 | , data = $this.data('alert') 79 | if (!data) $this.data('alert', (data = new Alert(this))) 80 | if (typeof option == 'string') data[option].call($this) 81 | }) 82 | } 83 | 84 | $.fn.alert.Constructor = Alert 85 | 86 | 87 | /* ALERT DATA-API 88 | * ============== */ 89 | 90 | $(function () { 91 | $('body').on('click.alert.data-api', dismiss, Alert.prototype.close) 92 | }) 93 | 94 | }( window.jQuery ); -------------------------------------------------------------------------------- /lib/bootstrap-dropdown.js: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrap-dropdown.js v2.0.1 3 | * http://twitter.github.com/bootstrap/javascript.html#dropdowns 4 | * ============================================================ 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function( $ ){ 22 | 23 | "use strict" 24 | 25 | /* DROPDOWN CLASS DEFINITION 26 | * ========================= */ 27 | 28 | var toggle = '[data-toggle="dropdown"]' 29 | , Dropdown = function ( element ) { 30 | var $el = $(element).on('click.dropdown.data-api', this.toggle) 31 | $('html').on('click.dropdown.data-api', function () { 32 | $el.parent().removeClass('open') 33 | }) 34 | } 35 | 36 | Dropdown.prototype = { 37 | 38 | constructor: Dropdown 39 | 40 | , toggle: function ( e ) { 41 | var $this = $(this) 42 | , selector = $this.attr('data-target') 43 | , $parent 44 | , isActive 45 | 46 | if (!selector) { 47 | selector = $this.attr('href') 48 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 49 | } 50 | 51 | $parent = $(selector) 52 | $parent.length || ($parent = $this.parent()) 53 | 54 | isActive = $parent.hasClass('open') 55 | 56 | clearMenus() 57 | !isActive && $parent.toggleClass('open') 58 | 59 | return false 60 | } 61 | 62 | } 63 | 64 | function clearMenus() { 65 | $(toggle).parent().removeClass('open') 66 | } 67 | 68 | 69 | /* DROPDOWN PLUGIN DEFINITION 70 | * ========================== */ 71 | 72 | $.fn.dropdown = function ( option ) { 73 | return this.each(function () { 74 | var $this = $(this) 75 | , data = $this.data('dropdown') 76 | if (!data) $this.data('dropdown', (data = new Dropdown(this))) 77 | if (typeof option == 'string') data[option].call($this) 78 | }) 79 | } 80 | 81 | $.fn.dropdown.Constructor = Dropdown 82 | 83 | 84 | /* APPLY TO STANDARD DROPDOWN ELEMENTS 85 | * =================================== */ 86 | 87 | $(function () { 88 | $('html').on('click.dropdown.data-api', clearMenus) 89 | $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle) 90 | }) 91 | 92 | }( window.jQuery ); -------------------------------------------------------------------------------- /lib/bootstrap-modal.js: -------------------------------------------------------------------------------- 1 | /* ========================================================= 2 | * bootstrap-modal.js v2.0.1 3 | * http://twitter.github.com/bootstrap/javascript.html#modals 4 | * ========================================================= 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================= */ 19 | 20 | 21 | !function( $ ){ 22 | 23 | "use strict" 24 | 25 | /* MODAL CLASS DEFINITION 26 | * ====================== */ 27 | 28 | var Modal = function ( content, options ) { 29 | this.options = options 30 | this.$element = $(content) 31 | .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) 32 | } 33 | 34 | Modal.prototype = { 35 | 36 | constructor: Modal 37 | 38 | , toggle: function () { 39 | return this[!this.isShown ? 'show' : 'hide']() 40 | } 41 | 42 | , show: function () { 43 | var that = this 44 | 45 | if (this.isShown) return 46 | 47 | $('body').addClass('modal-open') 48 | 49 | this.isShown = true 50 | this.$element.trigger('show') 51 | 52 | escape.call(this) 53 | backdrop.call(this, function () { 54 | var transition = $.support.transition && that.$element.hasClass('fade') 55 | 56 | !that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position 57 | 58 | that.$element 59 | .show() 60 | 61 | if (transition) { 62 | that.$element[0].offsetWidth // force reflow 63 | } 64 | 65 | that.$element.addClass('in') 66 | 67 | transition ? 68 | that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) : 69 | that.$element.trigger('shown') 70 | 71 | }) 72 | } 73 | 74 | , hide: function ( e ) { 75 | e && e.preventDefault() 76 | 77 | if (!this.isShown) return 78 | 79 | var that = this 80 | this.isShown = false 81 | 82 | $('body').removeClass('modal-open') 83 | 84 | escape.call(this) 85 | 86 | this.$element 87 | .trigger('hide') 88 | .removeClass('in') 89 | 90 | $.support.transition && this.$element.hasClass('fade') ? 91 | hideWithTransition.call(this) : 92 | hideModal.call(this) 93 | } 94 | 95 | } 96 | 97 | 98 | /* MODAL PRIVATE METHODS 99 | * ===================== */ 100 | 101 | function hideWithTransition() { 102 | var that = this 103 | , timeout = setTimeout(function () { 104 | that.$element.off($.support.transition.end) 105 | hideModal.call(that) 106 | }, 500) 107 | 108 | this.$element.one($.support.transition.end, function () { 109 | clearTimeout(timeout) 110 | hideModal.call(that) 111 | }) 112 | } 113 | 114 | function hideModal( that ) { 115 | this.$element 116 | .hide() 117 | .trigger('hidden') 118 | 119 | backdrop.call(this) 120 | } 121 | 122 | function backdrop( callback ) { 123 | var that = this 124 | , animate = this.$element.hasClass('fade') ? 'fade' : '' 125 | 126 | if (this.isShown && this.options.backdrop) { 127 | var doAnimate = $.support.transition && animate 128 | 129 | this.$backdrop = $('