A sorter site for Idolm@ster Characters
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Autosave feature, added some info, keyboard controls

execfera 00e6162f fff03560

+96 -22
+10 -7
index.html
··· 1 1 <html> 2 2 3 3 <head> 4 - <!-- Metadata --> 5 4 <link rel="shortcut icon" href="src/assets/yinyang.ico" type="image/x-icon"> 6 5 <link rel="icon" href="src/assets/yinyang.ico" type="image/x-icon"> 7 6 <meta charset="utf-8"> ··· 21 20 <script src="src/js/lz-string.min.js"></script> 22 21 <script src="src/js/seedrandom.min.js"></script> 23 22 <script src="src/js/main.js"></script> 24 - 25 - <!-- 4chan identifier tripcode: !FreliaEfl2 --> 26 23 </head> 27 24 28 25 <body> ··· 39 36 <img src="src/assets/defaultL.jpg" class="left sort image"> 40 37 41 38 <div class="starting start button">Touhou Project Character Sorter<br><br>Click to Start!</div> 42 - <div class="starting load button">Load Progress</div> 39 + <div class="starting load button">Load <span></span></div> 43 40 44 41 <div class="loading button"><div></div><span>Loading...</span></div> 45 42 ··· 47 44 <div class="sorting undo button">Undo</div> 48 45 <div class="sorting save button">Save Progress</div> 49 46 50 - <div class="finished save button">Save Result</div> 47 + <div class="finished save button">Generate Result URL</div> 51 48 <div class="finished getimg button">Generate Image</div> 52 49 <div class="finished list button">Generate Text List</div> 53 50 ··· 62 59 <div class="results"></div> 63 60 64 61 <div class="info"> 65 - <a href="https://relick.me/song/">Song Sorter</a> | <a href="mailto:fera@imouto.my">Contact</a> 62 + <a href="https://relick.me/song/">Song Sorter</a> | <a href="mailto:fera@imouto.my">Contact</a> | <a href="https://github.com/execfera/charasort/">Source Code</a> | <a class="clearsave">Clear Save Data</a> 66 63 67 64 <br><br> 68 65 ··· 70 67 <p><strong>Certain options have details that you can hover to read.</strong></p> 71 68 <p>Click on the character you like better from the two, or tie them if you like them equally or don't know them.</p> 72 69 <p>Depending on how many sources you pick, you'll get up to 700+ picks, so set aside a good few cups of tea for this.</p> 70 + 71 + <br><br> 72 + 73 + <p>Keyboard controls during sorting: H/LeftArrow (pick left) J/DownArrow (undo) K/UpArrow (tie) L/RightArrow (pick right) S (save progress).</p> 74 + <p>Before sorting: S/Enter (start sorting) L (load progress). 75 + <p>1/2/3 always correspond to the first/second/third buttons.</p> 73 76 74 77 <br><br> 75 78 ··· 77 80 78 81 <br><br> 79 82 80 - <p>Month Xth, 2018 - Refactored site.</p> 83 + <p>February 21st, 2018 - Refactored site. Autosave, shareable URLs, keyboard controls. Unfortunately, this update breaks support for older mobile Safari users. Get a better device or use a desktop.</p> 81 84 <p>January 7th, 2018 - Added Antinomy of Common Flowers characters.</p> 82 85 <p>August 11th, 2017 - Added Hidden Star in Four Seasons full version characters.</p> 83 86 </div>
+7 -1
src/css/styles.css
··· 54 54 cursor: pointer; 55 55 } 56 56 57 - .starting.button { 57 + .starting.start.button { 58 + grid-row: span 6; 59 + } 60 + 61 + .starting.load.button { 58 62 grid-row: span 3; 63 + display: none; 59 64 } 60 65 61 66 .sorting.button, .finished.button { ··· 261 266 color: #990000; 262 267 font-weight: bold; 263 268 text-decoration: none; 269 + cursor: pointer; 264 270 } 265 271 266 272 a:hover {
+1 -1
src/js/data/2017-05-01.js
··· 570 570 }, 571 571 { name: "Tokiko", img: "Y4maOc8.png", opts: { series: ["book"], stage: [] } }, 572 572 { 573 - name: "Reisen (Manga)", 573 + name: "Rei'sen (Manga)", 574 574 img: "cWjCo2j.png", 575 575 opts: { series: ["book"], stage: [] } 576 576 },
+7 -3
src/js/data/2018-02-20.js
··· 850 850 stage: [] 851 851 } 852 852 }, 853 - { name: "Tokiko", img: "Y4maOc8.png", opts: { 853 + { 854 + name: "Tokiko", 855 + img: "Y4maOc8.png", 856 + opts: { 854 857 series: ["book"], 855 858 stage: [] 856 - } }, 859 + } 860 + }, 857 861 { 858 - name: "Reisen (Manga)", 862 + name: "Rei'sen (Manga)", 859 863 img: "cWjCo2j.png", 860 864 opts: { 861 865 series: ["book"],
+71 -10
src/js/main.js
··· 50 50 let finalCharacters = []; 51 51 let loading = false; 52 52 let totalBattles = 0; 53 + let storedSaveType = localStorage.getItem('saveType'); 53 54 54 55 /** Initialize script. */ 55 56 function init() { ··· 62 63 63 64 document.querySelector('.sorting.tie.button').addEventListener('click', () => pick('tie')); 64 65 document.querySelector('.sorting.undo.button').addEventListener('click', undo); 65 - document.querySelector('.sorting.save.button').addEventListener('click', saveProgress); 66 + document.querySelector('.sorting.save.button').addEventListener('click', () => saveProgress('Progress')); 66 67 67 - document.querySelector('.finished.save.button').addEventListener('click', saveProgress); 68 + document.querySelector('.finished.save.button').addEventListener('click', () => saveProgress('Last Result')); 68 69 document.querySelector('.finished.getimg.button').addEventListener('click', generateImage); 69 70 document.querySelector('.finished.list.button').addEventListener('click', generateTextList); 70 71 72 + document.querySelector('.clearsave').addEventListener('click', clearProgress); 73 + 74 + /** Define keyboard controls (up/down/left/right vimlike k/j/h/l). */ 75 + document.addEventListener('keypress', (ev) => { 76 + /** If sorting is in progress. */ 77 + if (timestamp && !loading && choices.length !== battleNo - 1) { 78 + switch(ev.key) { 79 + case 's': case '3': saveProgress('Progress'); break; 80 + case 'h': case 'ArrowLeft': pick('left'); break; 81 + case 'l': case 'ArrowRight': pick('right'); break; 82 + case 'k': case '1': case 'ArrowUp': pick('tie'); break; 83 + case 'j': case '2': case 'ArrowDown': undo(); break; 84 + default: break; 85 + } 86 + } 87 + /** If sorting has ended. */ 88 + if (timeTaken && choices.length === battleNo - 1) { 89 + switch(ev.key) { 90 + case 'k': case '1': saveProgress('Last Result'); break; 91 + case 'j': case '2': generateImage(); break; 92 + case 's': case '3': generateTextList(); break; 93 + default: break; 94 + } 95 + } else { // If sorting hasn't started yet. 96 + switch(ev.key) { 97 + case '1': case 's': case 'Enter': start(); break; 98 + case '2': case 'l': loadProgress(); break; 99 + default: break; 100 + } 101 + } 102 + }); 103 + 71 104 document.querySelector('.image.selector').insertAdjacentElement('beforeend', document.createElement('select')); 72 105 106 + /** Initialize image quantity selector for results. */ 73 107 for (let i = 1; i <= 10; i++) { 74 108 const select = document.createElement('option'); 75 109 select.value = i; ··· 83 117 result(Number(imageNum)); 84 118 }); 85 119 120 + /** Show load button if save data exists. */ 121 + if (storedSaveType) { 122 + document.querySelector('.starting.load.button > span').insertAdjacentText('beforeend', storedSaveType); 123 + document.querySelectorAll('.starting.button').forEach(el => { 124 + el.style['grid-row'] = 'span 3'; 125 + el.style.display = 'block'; 126 + }); 127 + } 128 + 86 129 setLatestDataset(); 87 130 88 131 /** Decode query string if available. */ ··· 209 252 document.querySelectorAll('.starting.button').forEach(el => el.style.display = 'none'); 210 253 document.querySelector('.loading.button').style.display = 'block'; 211 254 document.querySelector('.progress').style.display = 'block'; 255 + document.querySelector('.info').style.display = 'none'; 212 256 loading = true; 213 257 214 258 preloadImages().then(() => { ··· 244 288 case 2: pick('tie'); break; 245 289 default: break; 246 290 } 247 - } 291 + } else { saveProgress('Autosave'); } 248 292 } 249 293 250 294 /** ··· 473 517 } 474 518 475 519 /** 476 - * Save progress to local browser storage and generate save URL. 520 + * Save progress to local browser storage. 521 + * 522 + * @param {'Autosave'|'Progress'|'Last Result'} saveType 477 523 */ 478 - function saveProgress() { 524 + function saveProgress(saveType) { 479 525 const saveData = generateSavedata(); 480 526 481 527 localStorage.setItem('saveData', saveData); 528 + localStorage.setItem('saveType', saveType); 482 529 483 - const saveURL = `${window.location.origin}${window.location.pathname}?${saveData}`; 484 - const inProgressText = 'You may click Load Progress after this to resume, or use this URL.'; 485 - const finishedText = 'You may use this URL to share this result.'; 530 + if (saveType !== 'Autosave') { 531 + const saveURL = `${window.location.origin}${window.location.pathname}?${saveData}`; 532 + const inProgressText = 'You may click Load Progress after this to resume, or use this URL.'; 533 + const finishedText = 'You may use this URL to share this result, or click Load Last Result to view it again.'; 486 534 487 - window.prompt(timeTaken ? finishedText : inProgressText, saveURL); 535 + window.prompt(saveType === 'Last Result' ? finishedText : inProgressText, saveURL); 536 + } 488 537 } 489 538 490 539 /** ··· 494 543 const saveData = localStorage.getItem('saveData'); 495 544 496 545 if (saveData) decodeQuery(saveData); 546 + } 547 + 548 + /** 549 + * Clear progress from local browser storage. 550 + */ 551 + function clearProgress() { 552 + storedSaveType = ''; 553 + 554 + localStorage.removeItem('saveData'); 555 + localStorage.removeItem('saveType'); 556 + 557 + document.querySelectorAll('.starting.start.button').forEach(el => el.style['grid-row'] = 'span 6'); 558 + document.querySelectorAll('.starting.load.button').forEach(el => el.style.display = 'none'); 497 559 } 498 560 499 561 function generateImage() { ··· 653 715 654 716 successfulLoad = true; 655 717 } catch (err) { 656 - alert(`Error loading shareable link: ${err}`); 657 718 console.error(`Error loading shareable link: ${err}`); 658 719 setLatestDataset(); // Restore to default function if loading link does not work. 659 720 }