Merge pull request #10 from whscullin/whscullin/de-jquery

Remove jQuery and jQuery UI dependencies.
This commit is contained in:
Will Scullin 2019-03-14 20:19:55 -07:00 committed by GitHub
commit 805155d842
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 991 additions and 839 deletions

View File

@ -27,26 +27,8 @@
<link rel="apple-touch-icon" size="72x72" href="img/webapp-ipad.png" /> <link rel="apple-touch-icon" size="72x72" href="img/webapp-ipad.png" />
<link rel="shortcut icon" href="img/logoicon.png" /> <link rel="shortcut icon" href="img/logoicon.png" />
<link rel="stylesheet" type="text/css" href="css/apple2.css" /> <link rel="stylesheet" type="text/css" href="css/apple2.css" />
<link rel="stylesheet" type="text/css"
href="//code.jquery.com/ui/1.10.3/themes/mint-choc/jquery-ui.css" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.2/css/all.css" /> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.2/css/all.css" />
<!-- white text in controls -->
<style type="text/css">
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
color: white;
}
.ui-state-default .ui-icon {
background-image: url(//code.jquery.com/ui/1.10.3/themes/mint-choc/images/ui-icons_ffffff_256x240.png);
}
</style>
<!-- jQuery -->
<script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js">
</script>
<script type="text/javascript" src="//code.jquery.com/ui/1.10.3/jquery-ui.js">
</script>
<!-- Disk Index --> <!-- Disk Index -->
<script type="text/javascript" src="json/disks/index.js"></script> <script type="text/javascript" src="json/disks/index.js"></script>
@ -55,12 +37,8 @@
ondragover="handleDragOver(0, event)" ondragover="handleDragOver(0, event)"
ondrop="handleDrop(0, event)" ondrop="handleDrop(0, event)"
ondragend="handleDragEnd(0, event)"> ondragend="handleDragEnd(0, event)">
<div id="fb-root"></div>
<div style="margin: auto; width: 614px"> <div style="margin: auto; width: 614px">
<div id="header"> <div id="header">
<a href="//www.w3.org/html/logo/" target="_blank">
<img src="//www.w3.org/html/logo/badge/html5-badge-h-solo.png" style="float: right" />
</a>
<a href="about.html" target="_blank"> <a href="about.html" target="_blank">
<img src="img/badge.png" id="badge" /> <img src="img/badge.png" id="badge" />
</a> </a>
@ -75,7 +53,7 @@
<div style="float: left; width: 50%" <div style="float: left; width: 50%"
ondragover="handleDragOver(1, event)" ondragover="handleDragOver(1, event)"
ondrop="handleDrop(1, event)" ondrop="handleDrop(1, event)"
ondragend="handleDragEnd(2, event)"> ondragend="handleDragEnd(1, event)">
<button id="diskload1" class="diskload" title="Load Disk" <button id="diskload1" class="diskload" title="Load Disk"
onclick="openLoad(1, event);"> onclick="openLoad(1, event);">
<i class="fas fa-folder-open"></i> <i class="fas fa-folder-open"></i>
@ -112,14 +90,14 @@
<button id="toggle-sound" onclick="toggleSound()" title="Toggle Sound"> <button id="toggle-sound" onclick="toggleSound()" title="Toggle Sound">
<i class="fas fa-volume-off"></i> <i class="fas fa-volume-off"></i>
</button> </button>
<button id="toggle-printer" onclick="$('#printer').dialog('open')" title="Toggle Printer"> <button id="toggle-printer" onclick="openPrinterModal()" title="Toggle Printer">
<i class="fas fa-print"></i> <i class="fas fa-print"></i>
</button> </button>
<div style="float: right"> <div style="float: right">
<a class="button" href="about.html" target="_blank" title="About"> <button onclick="window.open('about.html', 'blank')" title="About">
<i class="fas fa-info"></i> <i class="fas fa-info"></i>
</a> </button>
<button onclick="$('#options').dialog('open')" title="Options"> <button onclick="openOptions()" title="Options">
<i class="fas fa-cog"></i> <i class="fas fa-cog"></i>
</button> </button>
</div> </div>
@ -143,151 +121,261 @@
<label for="text_input">Text Input</label> <label for="text_input">Text Input</label>
<textarea rows="10" style="width: 99%" id="text_input"></textarea> <textarea rows="10" style="width: 99%" id="text_input"></textarea>
<br /> <br />
<button onclick="io.setKeyBuffer($('#text_input').val())"> <button onclick="io.setKeyBuffer(document.querySelector('#text_input').innerText)">
Send Send
</button> </button>
<input type="checkbox" id="buffering" /> <input type="checkbox" id="buffering" />
<label for="buffering">Buffer</label> <label for="buffering">Buffer</label>
<button style="float: right" <button style="float: right"
onclick="$('#keyboard').show(); $('#textarea').hide()"> onclick="document.querySelector('#keyboard').style.display = 'block'; document.querySelector('#textarea').style.display = 'none'">
Keyboard Keyboard
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<div id="loading" title="Loading" style="display: none">
Loading...
</div> </div>
<div id="options" title="Options" style="display: none">
<h3>Type</h3> <div class="modal" id="loading-modal" aria-hidden="true">
<ul> <div class="modal__overlay" tabindex="-1" data-micromodal-close>
<li> <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Loading" >
<select id="computer_type2" value="apple2plus" onchange="updateCPU()"> <header class="modal__header">
<option value="apple2plus">Apple ][+</option> <span class="modal__title" id="loading-modal-title">
<option value="apple2">Autostart Apple ][</option> Loading...
<option value="original">Apple ][</option> </span>
<option value="apple2j">Apple ][j+</option> </header>
<option value="apple2lc">Apple ][+ (lowercase font)</option> </div>
<option value="apple2pig">Apple ][+ (pig font)</option>
</select>
</li>
<li>
<i>* Reload page to take effect</i>
</li>
</ul>
<h3>CPU</h3>
<ul>
<li>
<input type="checkbox" id="accelerator_toggle" onclick="updateCPU()"/>
<label for="accelerator_toggle">
Accelerated CPU
</label>
</li>
</ul>
<h3>Joystick</h3>
<ul>
<li>
<input type="checkbox" id="disable_mouse"
onclick="updateJoystick()" />
<label for="disable_mouse">
Disable Mouse Joystick
</label>
</li>
<li>
<input type="checkbox" id="flip_x"
onclick="updateJoystick()" />
<label for="flip_x">
Flip X-Axis
</label>
</li>
<li>
<input type="checkbox" id="flip_y"
onclick="updateJoystick()" />
<label for="flip_y">
Flip Y-Axis
</label>
</li>
<li>
<input type="checkbox" id="swap_x_y"
onclick="updateJoystick()" />
<label for="swap_x_y">
Swap X-Y Axis
</label>
</li>
</ul>
<h3>Monitor</h3>
<ul>
<li>
<input type="checkbox" id="green_screen"
onclick="updateScreen()" />
<label for="green_screen">
Green Screen
</label>
</li>
<li>
<input type="checkbox" id="show_scanlines"
onclick="updateScreen()" />
<label for="show_scanlines">
Show Scanlines
</label>
</li>
</ul>
<h3>Sound</h3>
<ul>
<li>
<input type="checkbox" id="enable_sound"
onclick="updateSound()" checked="checked" />
<label for="enable_sound">
Enable (Experimental)
</label>
</li>
</ul>
</div>
<div id="save" title="Save Disk" style="display: none">
<form action="#" onsubmit="return false;">
<b>Save to Browser</b>
<br /><br />
Save Name: <input type="text" name="name" id="save_name"
style="width: 200px" />
</form>
<hr />
<div>
<b>Download to Local Disk</b>
<br /><br />
<a id="local_save_link" class="button">Download</a>
</div> </div>
</div> </div>
<div id="manage" title="Manage Disks" style="display: none">
<div class="modal" id="options-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Options">
<header class="modal__header">
<span class="modal__title" id="options-modal-title">
Options
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="options-modal-content">
<h3>Type</h3>
<ul>
<li>
<select id="computer_type2" value="apple2plus" onchange="updateCPU()">
<option value="apple2plus">Apple ][+</option>
<option value="apple2">Autostart Apple ][</option>
<option value="original">Apple ][</option>
<option value="apple2j">Apple ][j+</option>
<option value="apple2lc">Apple ][+ (lowercase font)</option>
<option value="apple2pig">Apple ][+ (pig font)</option>
</select>
</li>
<li>
<i>* Reload page to take effect</i>
</li>
</ul>
<h3>CPU</h3>
<ul>
<li>
<input type="checkbox" id="accelerator_toggle" onclick="updateCPU()"/>
<label for="accelerator_toggle">
Accelerated CPU
</label>
</li>
</ul>
<h3>Joystick</h3>
<ul>
<li>
<input type="checkbox" id="disable_mouse"
onclick="updateJoystick()" />
<label for="disable_mouse">
Disable Mouse Joystick
</label>
</li>
<li>
<input type="checkbox" id="flip_x"
onclick="updateJoystick()" />
<label for="flip_x">
Flip X-Axis
</label>
</li>
<li>
<input type="checkbox" id="flip_y"
onclick="updateJoystick()" />
<label for="flip_y">
Flip Y-Axis
</label>
</li>
<li>
<input type="checkbox" id="swap_x_y"
onclick="updateJoystick()" />
<label for="swap_x_y">
Swap X-Y Axis
</label>
</li>
</ul>
<h3>Monitor</h3>
<ul>
<li>
<input type="checkbox" id="green_screen"
onclick="updateScreen()" />
<label for="green_screen">
Green Screen
</label>
</li>
<li>
<input type="checkbox" id="show_scanlines"
onclick="updateScreen()" />
<label for="show_scanlines">
Show Scanlines
</label>
</li>
</ul>
<h3>Sound</h3>
<ul>
<li>
<input type="checkbox" id="enable_sound"
onclick="updateSound()" checked="checked" />
<label for="enable_sound">
Enable
</label>
</li>
</ul>
</main>
<footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Close</button>
</footer>
</div>
</div>
</div> </div>
<div id="http_load" title="Load URL" style="display: none">
<form action="#"> <div class="modal" id="save-modal" aria-hidden="true">
<input type="text" id="http_url" style="width: 500px"/> <div class="modal__overlay" tabindex="-1" data-micromodal-close>
</form> <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Save Disk">
<header class="modal__header">
<span class="modal__title" id="save-modal-title">
Save Disk
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="save-modal-content">
<form action="#" onsubmit="return false;">
<h3>Save to Browser</h3>
Save Name: <input type="text" name="name" id="save_name"
style="width: 200px" />
</form>
<hr />
<div>
<h3>Download to Local Disk</h3>
<a id="local_save_link" class="button">Download</a>
</div>
</main>
<footer class="modal__footer">
<button class="modal__btn" onclick="doSave()" aria-label="Save disk locally">Save</button>
</footer>
</div>
</div>
</div> </div>
<div id="load" title="Load Disk" style="display: none">
<table> <div class="modal" id="manage-modal" aria-hidden="true">
<tr> <div class="modal__overlay" tabindex="-1" data-micromodal-close>
<td> <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Load Disk">
<select id="category_select" multiple="multiple" <header class="modal__header">
class="ui-widget ui-state-default" <span class="modal__title" id="manage-modal-title">
onchange="selectCategory(event)" > Manage Local Saves
</select> </span>
</td> <button class="modal__close" aria-label="Close modal" data-micromodal-close>
<td> </button>
<select id="disk_select" multiple="multiple" </header>
class="ui-widget ui-state-default" <main class="modal__content" id="manage-modal-content">
onchange="selectDisk(event)" </main>
ondblclick="clickDisk(event)"> <footer class="modal__footer">
</select> <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">OK</button>
</td> </footer>
</tr> </div>
</table> </div>
<form action="#">
<input type="file" id="local_file" />
</form>
</div> </div>
<div id="printer" title="Printer" style="display: none">
<div class="paper"> <div class="modal" id="http-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Load Disk">
<header class="modal__header">
<span class="modal__title" id="http-modal-title">
Load URL
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="http-modal-content">
<form action="#">
<input type="text" id="http_url" style="width: 500px"/>
</form>
</main>
<footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">OK</button>
</footer>
</div>
</div>
</div>
<div class="modal" id="load-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Load Disk">
<header class="modal__header">
<span class="modal__title" id="load-modal-title">
Load Disk
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="load-modal-content">
<table>
<tr>
<td>
<select id="category_select" multiple="multiple"
onchange="selectCategory(event)" >
</select>
</td>
<td>
<select id="disk_select" multiple="multiple"
onchange="selectDisk(event)"
ondblclick="clickDisk(event)">
</select>
</td>
</tr>
</table>
<form action="#">
<input type="file" id="local_file" />
</form>
</main>
<footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Cancel</button>
<button class="modal__btn" onclick="doLoad()" aria-label="Open the selected disk">Open</button>
</footer>
</div>
</div>
</div>
<div class="modal" id="printer-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Printer">
<header class="modal__header">
<span class="modal__title" id="printer-modal-title">
Printer
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="printer-modal-content">
<div class="feed">
<div class="paper"></div>
</div>
</main>
<footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Close</button>
</footer>
</div>
</div> </div>
</div> </div>
<script src="dist/main2.js"></script> <script src="dist/main2.js"></script>

View File

@ -27,26 +27,8 @@
<link rel="apple-touch-icon" size="72x72" href="img/webapp-ipad.png" /> <link rel="apple-touch-icon" size="72x72" href="img/webapp-ipad.png" />
<link rel="shortcut icon" href="img/logoicon.png" /> <link rel="shortcut icon" href="img/logoicon.png" />
<link rel="stylesheet" type="text/css" href="css/apple2.css" /> <link rel="stylesheet" type="text/css" href="css/apple2.css" />
<link rel="stylesheet" type="text/css"
href="//code.jquery.com/ui/1.10.3/themes/mint-choc/jquery-ui.css" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.2/css/all.css" /> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.2/css/all.css" />
<!-- white text in controls -->
<style type="text/css">
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
color: white;
}
.ui-state-default .ui-icon {
background-image: url(//code.jquery.com/ui/1.10.3/themes/mint-choc/images/ui-icons_ffffff_256x240.png);
}
</style>
<!-- jQuery -->
<script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js">
</script>
<script type="text/javascript" src="//code.jquery.com/ui/1.10.3/jquery-ui.js">
</script>
<!-- Disk Index --> <!-- Disk Index -->
<script type="text/javascript" src="json/disks/index.js"></script> <script type="text/javascript" src="json/disks/index.js"></script>
@ -57,9 +39,6 @@
ondragend="handleDragEnd(0, event)"> ondragend="handleDragEnd(0, event)">
<div class="outer"> <div class="outer">
<div id="header"> <div id="header">
<a href="//www.w3.org/html/logo/" target="_blank">
<img src="//www.w3.org/html/logo/badge/html5-badge-h-solo.png" style="float: right" />
</a>
<a href="about.html" target="_blank"> <a href="about.html" target="_blank">
<img src="img/badge2e.png" id="badge" /> <img src="img/badge2e.png" id="badge" />
</a> </a>
@ -114,14 +93,14 @@
<button id="toggle-sound" onclick="toggleSound()"> <button id="toggle-sound" onclick="toggleSound()">
<i class="fas fa-volume-off"></i> <i class="fas fa-volume-off"></i>
</button> </button>
<button id="toggle-printer" onclick="$('#printer').dialog('open')" title="Toggle Printer"> <button id="toggle-printer" onclick="openPrinterModal()" title="Toggle Printer">
<i class="fas fa-print"></i> <i class="fas fa-print"></i>
</button> </button>
<div style="float: right"> <div style="float: right">
<a class="button" href="about.html" target="_blank" title="About"> <button onclick="window.open('about.html', 'blank')" title="About">
<i class="fas fa-info"></i> <i class="fas fa-info"></i>
</a> </button>
<button onclick="$('#options').dialog('open')"> <button onclick="openOptions()">
<i class="fas fa-cog"></i> <i class="fas fa-cog"></i>
</button> </button>
</div> </div>
@ -134,138 +113,245 @@
<div id="keyboard"></div> <div id="keyboard"></div>
</div> </div>
</div> </div>
<div id="loading" title="Loading" style="display: none">
Loading... <div class="modal" id="loading-modal" aria-hidden="true">
</div> <div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div id="options" title="Options" style="display: none"> <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Loading" >
<h3>Type</h3> <header class="modal__header">
<ul> <span class="modal__title" id="loading-modal-title">
<li> Loading...
<select id="computer_type2e" value="apple2enh" onchange="updateCPU()"> </span>
<option value="apple2enh">Enhanced Apple //e</option> </header>
<option value="apple2e">Apple //e</option> </div>
<option value="apple2rm">Enhanced Apple //e (Reactive Micro)</option>
</select>
</li>
<li>
<i>* Reload page to take effect</i>
</li>
</ul>
<h3>CPU</h3>
<ul>
<li>
<input type="checkbox" id="accelerator_toggle" onclick="updateCPU()"/>
<label for="accelerator_toggle">
Accelerated CPU
</label>
</li>
</ul>
<h3>Joystick</h3>
<ul>
<li>
<input type="checkbox" id="disable_mouse"
onclick="updateJoystick()" />
<label for="disable_mouse">
Disable Mouse Joystick
</label>
</li>
<li>
<input type="checkbox" id="flip_x"
onclick="updateJoystick()" />
<label for="flip_x">
Flip X-Axis
</label>
</li>
<li>
<input type="checkbox" id="flip_y"
onclick="updateJoystick()" />
<label for="flip_y">
Flip Y-Axis
</label>
</li>
<li>
<input type="checkbox" id="swap_x_y"
onclick="updateJoystick()" />
<label for="swap_x_y">
Swap X-Y Axis
</label>
</li>
</ul>
<h3>Monitor</h3>
<ul>
<li>
<input type="checkbox" id="green_screen"
onclick="updateScreen()" />
<label for="green_screen">
Green Screen
</label>
</li>
<li>
<input type="checkbox" id="show_scanlines"
onclick="updateScreen()" />
<label for="show_scanlines">
Show Scanlines
</label>
</li>
</ul>
<h3>Sound</h3>
<ul>
<li>
<input type="checkbox" id="enable_sound"
onclick="updateSound()" checked="checked" />
<label for="enable_sound">
Enable (Experimental)
</label>
</li>
</ul>
</div>
<div id="save" title="Save Disk" style="display: none">
<form action="#" onsubmit="return false;">
<b>Save to Browser</b>
<br /><br />
Save Name: <input type="text" name="name" id="save_name"
style="width: 200px" />
</form>
<hr />
<div>
<b>Download to Local Disk</b>
<br /><br />
<a id="local_save_link" class="button">Download</a>
</div> </div>
</div> </div>
<div id="manage" title="Manage Disks" style="display: none">
</div> <div class="modal" id="options-modal" aria-hidden="true">
<div id="http_load" title="Load URL" style="display: none"> <div class="modal__overlay" tabindex="-1" data-micromodal-close>
<form action="#"> <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Options">
<input type="text" id="http_url" style="width: 500px"/> <header class="modal__header">
</form> <span class="modal__title" id="options-modal-title">
</div> Options
<div id="load" title="Load Disk" style="display: none"> </span>
<table> <button class="modal__close" aria-label="Close modal" data-micromodal-close>
<tr> </button>
<td> </header>
<select id="category_select" multiple="multiple" <main class="modal__content" id="options-modal-content">
class="ui-widget ui-state-default" <h3>Type</h3>
onchange="selectCategory(event)" > <ul>
</select> <li>
</td> <select id="computer_type2e" value="apple2enh" onchange="updateCPU()">
<td> <option value="apple2enh">Enhanced Apple //e</option>
<select id="disk_select" multiple="multiple" <option value="apple2e">Apple //e</option>
class="ui-widget ui-state-default" <option value="apple2rm">Enhanced Apple //e (Reactive Micro)</option>
onchange="selectDisk(event)" </select>
ondblclick="clickDisk(event)"> </li>
</select> <li>
</td> <i>* Reload page to take effect</i>
</tr> </li>
</table> </ul>
<form action="#"> <h3>CPU</h3>
<input type="file" id="local_file" /> <ul>
</form> <li>
</div> <input type="checkbox" id="accelerator_toggle" onclick="updateCPU()"/>
<div id="printer" title="Printer" style="display: none"> <label for="accelerator_toggle">
<div class="paper"> Accelerated CPU
</label>
</li>
</ul>
<h3>Joystick</h3>
<ul>
<li>
<input type="checkbox" id="disable_mouse"
onclick="updateJoystick()" />
<label for="disable_mouse">
Disable Mouse Joystick
</label>
</li>
<li>
<input type="checkbox" id="flip_x"
onclick="updateJoystick()" />
<label for="flip_x">
Flip X-Axis
</label>
</li>
<li>
<input type="checkbox" id="flip_y"
onclick="updateJoystick()" />
<label for="flip_y">
Flip Y-Axis
</label>
</li>
<li>
<input type="checkbox" id="swap_x_y"
onclick="updateJoystick()" />
<label for="swap_x_y">
Swap X-Y Axis
</label>
</li>
</ul>
<h3>Monitor</h3>
<ul>
<li>
<input type="checkbox" id="green_screen"
onclick="updateScreen()" />
<label for="green_screen">
Green Screen
</label>
</li>
<li>
<input type="checkbox" id="show_scanlines"
onclick="updateScreen()" />
<label for="show_scanlines">
Show Scanlines
</label>
</li>
</ul>
<h3>Sound</h3>
<ul>
<li>
<input type="checkbox" id="enable_sound"
onclick="updateSound()" checked="checked" />
<label for="enable_sound">
Enable
</label>
</li>
</ul>
</main>
<footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Close</button>
</footer>
</div>
</div> </div>
</div> </div>
<script type="text/javascript" src="dist/main2e.js"></script>
<div class="modal" id="save-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Save Disk">
<header class="modal__header">
<span id="save-modal-title">
Save Disk
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="save-modal-content">
<form action="#" onsubmit="return false;">
<h3>Save to Browser</h3>
Save Name: <input type="text" name="name" id="save_name"
style="width: 200px" />
</form>
<hr />
<div>
<h3>Download to Local Disk</h3>
<a id="local_save_link" class="button">Download</a>
</div>
</main>
<footer class="modal__footer">
<button class="modal__btn" onclick="doSave()" aria-label="Save disk locally">Save</button>
</footer>
</div>
</div>
</div>
<div class="modal" id="manage-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Load Disk">
<header class="modal__header">
<span class="modal__title" id="manage-modal-title">
Manage Local Saves
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="manage-modal-content">
</main>
<footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">OK</button>
</footer>
</div>
</div>
</div>
<div class="modal" id="http-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Load Disk">
<header class="modal__header">
<span class="modal__title" id="http-modal-title">
Load URL
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="http-modal-content">
<form action="#">
<input type="text" id="http_url" style="width: 500px"/>
</form>
</main>
<footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">OK</button>
</footer>
</div>
</div>
</div>
<div class="modal" id="load-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Load Disk">
<header class="modal__header">
<span class="modal__title" id="load-modal-title">
Load Disk
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="load-modal-content">
<table>
<tr>
<td>
<select id="category_select" multiple="multiple"
onchange="selectCategory(event)" >
</select>
</td>
<td>
<select id="disk_select" multiple="multiple"
onchange="selectDisk(event)"
ondblclick="clickDisk(event)">
</select>
</td>
</tr>
</table>
<form action="#">
<input type="file" id="local_file" />
</form>
</main>
<footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Cancel</button>
<button class="modal__btn" onclick="doLoad()" aria-label="Open the selected disk">Open</button>
</footer>
</div>
</div>
</div>
<div class="modal" id="printer-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="Printer">
<header class="modal__header">
<span class="modal__title" id="printer-modal-title">
Printer
</span>
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
</button>
</header>
<main class="modal__content" id="printer-modal-content">
<div class="paper"></div>
</main>
<footer class="modal__footer">
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Close</button>
</footer>
</div>
</div>
</div>
<script src="dist/main2e.js"></script>
</body> </body>
</html> </html>

View File

@ -52,7 +52,7 @@ input[type="text"] {
body { body {
margin: 16px 0; margin: 16px 0;
font-size: 10px; font-size: 14px;
background-color: #c4c1a0; /* Pantone 453 */ background-color: #c4c1a0; /* Pantone 453 */
font-family: sans-serif; font-family: sans-serif;
} }
@ -62,10 +62,6 @@ body {
width: 620px; width: 620px;
} }
label {
font-weight: bold;
}
#display { #display {
margin: 5px auto; margin: 5px auto;
} }
@ -134,7 +130,6 @@ label {
} }
.disklabel { .disklabel {
font-size: 11px;
font-family: sans-serif; font-family: sans-serif;
} }
@ -167,6 +162,10 @@ th {
margin: 10px 0; margin: 10px 0;
} }
.inset button {
min-width: 36px;
}
#khz { #khz {
margin-right: 4px; margin-right: 4px;
overflow: hidden; overflow: hidden;
@ -216,9 +215,109 @@ canvas {
color: #000; color: #000;
} }
#load select { #load-modal select {
width: 250px; width: 250px;
height: 300px; height: 300px;
font-size: 14px;
}
#load-modal input {
font-size: 14px;
line-height: 14px;
}
.modal {
display: none;
}
.modal.is-open {
display: block;
}
.modal__overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.6);
display: flex;
justify-content: center;
align-items: center;
}
.modal__container {
background-color: #c4c1a0;
padding: 10px;
max-height: 100vh;
border-radius: 4px;
overflow-y: auto;
box-sizing: border-box;
}
.modal__header {
display: flex;
font-size: 14px;
justify-content: space-between;
align-items: center;
background: #44372C;
color: #fff;
padding: 5px 11px;
border: 1px outset #66594E;
border-radius: 3px;
}
.modal__title {
margin-top: 0;
margin-bottom: 0;
font-weight: 600;
font-size: 1.25rem;
line-height: 1.25;
color: #fff;
box-sizing: border-box;
}
.modal__close, .modal__close:active, .modal__close:hover {
background: transparent;
padding: 3px;
}
.modal__header .modal__close:before {
content: "\2715";
}
.modal__content {
margin-top: 10px;
margin-bottom: 10px;
line-height: 1.5;
color: #000;
}
.modal__footer {
text-align: right;
}
button {
background: #44372C;
color: #fff;
padding: 2px 8px;
border: 1px outset #66594E;
border-radius: 3px;
font-size: 15px;
}
button:hover {
background-color: #55473D;
border: 1px outset #66594E;
}
button:active {
background-color: #22150A;
border: 1px outset #44372C;
}
button:focus {
outline: none;
} }
#keyboard { #keyboard {
@ -228,6 +327,7 @@ canvas {
-moz-user-select: none; -moz-user-select: none;
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
font-size: 10px;
} }
#keyboard .row { #keyboard .row {
@ -472,7 +572,7 @@ canvas {
width: 100%; width: 100%;
} }
.standalone #header, .standalone #social { .standalone #header {
display: none; display: none;
} }
@ -480,11 +580,29 @@ canvas {
font-family: courier; font-family: courier;
} }
#options { #options-modal {
line-height: 1.75em; width: 300px;
height: auto !important; line-height: 1.75em;
} }
#options li { #options-modal h3 {
font-size: 13px;
}
#options-modal li {
list-style-type: none; list-style-type: none;
} }
#printer-modal .feed {
width: 640px;
height: 480px;
overflow: auto;
}
#printer-modal .paper {
min-width: 640px;
min-height: 480px;
background-color: white;
color: black;
font-family: monospace;
}

View File

@ -12,6 +12,8 @@
import { base64_decode, base64_encode } from '../base64'; import { base64_decode, base64_encode } from '../base64';
import { bytify, debug } from '../util'; import { bytify, debug } from '../util';
export const DISK_TYPES = ['dsk','d13','do','po','raw','nib','2mg'];
export default function DiskII(io, slot, callbacks) export default function DiskII(io, slot, callbacks)
{ {
slot = slot || 6; slot = slot || 6;

View File

@ -1,3 +1,5 @@
import MicroModal from 'micromodal';
import Apple2IO from './apple2io'; import Apple2IO from './apple2io';
import ApplesoftDump from './applesoft/decompiler'; import ApplesoftDump from './applesoft/decompiler';
import { HiresPage, LoresPage, VideoModes } from './canvas'; import { HiresPage, LoresPage, VideoModes } from './canvas';
@ -7,12 +9,13 @@ import RAM from './ram';
import { debug, gup, hup } from './util'; import { debug, gup, hup } from './util';
import Audio from './ui/audio'; import Audio from './ui/audio';
import DriveLights from './ui/drive_lights';
import { gamepad, configGamepad, initGamepad, processGamepad } from './ui/gamepad'; import { gamepad, configGamepad, initGamepad, processGamepad } from './ui/gamepad';
import KeyBoard from './ui/keyboard'; import KeyBoard from './ui/keyboard';
import Printer from './ui/printer'; import Printer from './ui/printer';
import Tape from './ui/tape'; import Tape, { TAPE_TYPES } from './ui/tape';
import DiskII from './cards/disk2'; import DiskII, { DISK_TYPES } from './cards/disk2';
import LanguageCard from './cards/langcard'; import LanguageCard from './cards/langcard';
import Parallel from './cards/parallel'; import Parallel from './cards/parallel';
import RAMFactor from './cards/ramfactor'; import RAMFactor from './cards/ramfactor';
@ -46,86 +49,11 @@ var TRACE = false;
var MAX_TRACE = 256; var MAX_TRACE = 256;
var trace = []; var trace = [];
/*
* Page viewer
*/
/*
function PageDebug(page)
{
var _page = page;
function _init() {
var r, c;
var row = $('<tr />').appendTo('#page' + toHex(_page));
$('<th>\\</th>').appendTo(row);
for (c = 0; c < 16; c++) {
$('<th>' + toHex(c) + '</th>').appendTo(row);
}
for (r = 0; r < 16; r++) {
row = $('<tr />').appendTo('#page' + toHex(_page));
$('<th>' + toHex(r * 16) + '</th>').appendTo(row);
for (c = 0; c < 16; c++) {
$('<td>--</td>').appendTo(row).attr('id', 'page' + toHex(_page) + '-' + toHex(r * 16 + c));
}
}
}
_init();
return {
start: function() { return _page; },
end: function() { return _page; },
read: null,
write: function(page, off, val) {
$('#page' + toHex(page) + '-' + toHex(off)).text(toHex(val));
}
};
}
*/
var disk_categories = {'Local Saves': []}; var disk_categories = {'Local Saves': []};
var disk_sets = {}; var disk_sets = {};
var disk_cur_name = []; var disk_cur_name = [];
var disk_cur_cat = []; var disk_cur_cat = [];
function DriveLights()
{
return {
driveLight: function(drive, on) {
$('#disk' + drive).css('background-image',
on ? 'url(css/red-on-16.png)' :
'url(css/red-off-16.png)');
},
dirty: function() {
// $('#disksave' + drive).button('option', 'disabled', !dirty);
},
label: function(drive, label) {
if (label) {
$('#disklabel' + drive).text(label);
}
return $('#disklabel' + drive).text();
},
getState: function() {
return {
disks: [
this.label(1),
this.label(2)
]
};
},
setState: function(state) {
if (state && state.disks) {
this.label(1, state.disks[0].label);
this.label(2, state.disks[1].label);
}
}
};
}
var DISK_TYPES = ['dsk','d13','do','po','raw','nib','2mg'];
var TAPE_TYPES = ['wav','aiff','aif','mp3','m4a'];
var _currentDrive = 1; var _currentDrive = 1;
window.openLoad = function(drive, event) window.openLoad = function(drive, event)
@ -135,9 +63,10 @@ window.openLoad = function(drive, event)
openLoadHTTP(drive); openLoadHTTP(drive);
} else { } else {
if (disk_cur_cat[drive]) { if (disk_cur_cat[drive]) {
$('#category_select').val(disk_cur_cat[drive]).change(); document.querySelector('#category_select').value = disk_cur_cat[drive];
window.selectCategory();
} }
$('#load').dialog('open'); MicroModal.show('load-modal');
} }
}; };
@ -147,17 +76,17 @@ window.openSave = function(drive, event)
var mimetype = 'application/octet-stream'; var mimetype = 'application/octet-stream';
var data = disk2.getBinary(drive); var data = disk2.getBinary(drive);
var a = $('#local_save_link'); var a = document.querySelector('#local_save_link');
var blob = new Blob([data], { 'type': mimetype }); var blob = new Blob([data], { 'type': mimetype });
a.attr('href', window.URL.createObjectURL(blob)); a.href = window.URL.createObjectURL(blob);
a.attr('download', drivelights.label(drive) + '.dsk'); a.download = drivelights.label(drive) + '.dsk';
if (event.metaKey) { if (event.metaKey) {
dumpDisk(drive); dumpDisk(drive);
} else { } else {
$('#save_name').val(drivelights.label(drive)); document.querySelector('#save_name').value = drivelights.label(drive);
$('#save').dialog('open'); MicroModal.show('save-modal');
} }
}; };
@ -213,32 +142,29 @@ var loading = false;
function loadAjax(drive, url) { function loadAjax(drive, url) {
loading = true; loading = true;
$('#loading').dialog('open'); MicroModal.show('loading-modal');
$.ajax({ fetch(url).then(function(response) {
url: url, return response.json();
dataType: 'json', }).then(function(data) {
modifiedSince: true, if (data.type == 'binary') {
error: function(xhr, status, error) { loadBinary(drive, data);
alert(error || status); } else if (DISK_TYPES.includes(data.type)) {
$('#loading').dialog('close'); loadDisk(drive, data);
loading = false;
},
success: function(data) {
if (data.type == 'binary') {
loadBinary(drive, data);
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
loadDisk(drive, data);
}
initGamepad(data.gamepad);
$('#loading').dialog('close');
loading = false;
} }
initGamepad(data.gamepad);
MicroModal.close('loading-modal');
loading = false;
}).catch(function(error) {
window.alert(error || status);
MicroModal.close('loading-modal');
loading = false;
}); });
} }
function doLoad() { window.doLoad = function doLoad() {
var urls = $('#disk_select').val(), url; MicroModal.close('load-modal');
var urls = document.querySelector('#disk_select').value, url;
if (urls && urls.length) { if (urls && urls.length) {
if (typeof(urls) == 'string') { if (typeof(urls) == 'string') {
url = urls; url = urls;
@ -247,12 +173,12 @@ function doLoad() {
} }
} }
var files = $('#local_file').prop('files'); var files = document.querySelector('#local_file').files;
if (files.length == 1) { if (files.length == 1) {
doLoadLocal(_currentDrive, files[0]); doLoadLocal(_currentDrive, files[0]);
} else if (url) { } else if (url) {
var filename; var filename;
$('#load').dialog('close'); MicroModal.close('load-modal');
if (url.substr(0,6) == 'local:') { if (url.substr(0,6) == 'local:') {
filename = url.substr(6); filename = url.substr(6);
if (filename == '__manage') { if (filename == '__manage') {
@ -270,16 +196,15 @@ function doLoad() {
var parts = document.location.hash.split('|'); var parts = document.location.hash.split('|');
parts[_currentDrive - 1] = filename; parts[_currentDrive - 1] = filename;
document.location.hash = parts.join('|'); document.location.hash = parts.join('|');
loadAjax(_currentDrive, url);
} }
} }
} };
function doSave() { window.doSave = function doSave() {
var name = $('#save_name').val(); var name = document.querySelector('#save_name').value;
saveLocalStorage(_currentDrive, name); saveLocalStorage(_currentDrive, name);
$('#save').dialog('close'); MicroModal.close('save-modal');
} };
window.doDelete = function(name) { window.doDelete = function(name) {
if (window.confirm('Delete ' + name + '?')) { if (window.confirm('Delete ' + name + '?')) {
@ -290,15 +215,15 @@ window.doDelete = function(name) {
function doLoadLocal(drive, file) { function doLoadLocal(drive, file) {
var parts = file.name.split('.'); var parts = file.name.split('.');
var ext = parts[parts.length - 1].toLowerCase(); var ext = parts[parts.length - 1].toLowerCase();
if ($.inArray(ext, DISK_TYPES) >= 0) { if (DISK_TYPES.includes(ext)) {
doLoadLocalDisk(drive, file); doLoadLocalDisk(drive, file);
} else if ($.inArray(ext, TAPE_TYPES) >= 0) { } else if ($.inArray(ext, TAPE_TYPES) >= 0) {
tape.doLoadLocalTape(file, function() { tape.doLoadLocalTape(file, function() {
$('#load').dialog('close'); MicroModal.close('load-modal');
}); });
} else { } else {
window.alert('Unknown file type: ' + ext); window.alert('Unknown file type: ' + ext);
$('#load').dialog('close'); MicroModal.close('load-modal');
} }
} }
@ -310,7 +235,7 @@ function doLoadLocalDisk(drive, file) {
var name = parts.join('.'); var name = parts.join('.');
if (disk2.setBinary(drive, name, ext, this.result)) { if (disk2.setBinary(drive, name, ext, this.result)) {
drivelights.label(drive, name); drivelights.label(drive, name);
$('#load').dialog('close'); MicroModal.close('load-modal');
initGamepad(); initGamepad();
} }
}; };
@ -318,7 +243,7 @@ function doLoadLocalDisk(drive, file) {
} }
function doLoadHTTP(drive, _url) { function doLoadHTTP(drive, _url) {
var url = _url || $('#http_url').val(); var url = _url || document.querySelector('#http_url').value;
if (url) { if (url) {
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
req.open('GET', url, true); req.open('GET', url, true);
@ -332,7 +257,7 @@ function doLoadHTTP(drive, _url) {
var name = decodeURIComponent(fileParts.join('.')); var name = decodeURIComponent(fileParts.join('.'));
if (disk2.setBinary(drive, name, ext, req.response)) { if (disk2.setBinary(drive, name, ext, req.response)) {
drivelights.label(drive, name); drivelights.label(drive, name);
$('#http_load').dialog('close'); MicroModal.close('http-modal');
initGamepad(); initGamepad();
} }
}; };
@ -342,11 +267,11 @@ function doLoadHTTP(drive, _url) {
function openLoadHTTP(drive) { function openLoadHTTP(drive) {
_currentDrive = parseInt(drive, 10); _currentDrive = parseInt(drive, 10);
$('#http_load').dialog('open'); MicroModal.show('http-modal');
} }
function openManage() { function openManage() {
$('#manage').dialog('open'); MicroModal.show('manage-modal');
} }
var prefs = new Prefs(); var prefs = new Prefs();
@ -423,7 +348,7 @@ var io = new Apple2IO(cpu, vm);
var keyboard = new KeyBoard(cpu, io); var keyboard = new KeyBoard(cpu, io);
var audio = new Audio(io); var audio = new Audio(io);
var tape = new Tape(io); var tape = new Tape(io);
var printer = new Printer($('#printer .paper')); var printer = new Printer('#printer-modal .paper');
var lc = new LanguageCard(io, 0, rom); var lc = new LanguageCard(io, 0, rom);
var parallel = new Parallel(io, 1, printer); var parallel = new Parallel(io, 1, printer);
@ -460,11 +385,11 @@ function updateKHz() {
if (window.showFPS) { if (window.showFPS) {
delta = renderedFrames - lastFrames; delta = renderedFrames - lastFrames;
var fps = parseInt(delta/(ms/1000), 10); var fps = parseInt(delta/(ms/1000), 10);
$('#khz').text( fps + 'fps'); document.querySelector('#khz').innerText = fps + 'fps';
} else { } else {
delta = cycles - lastCycles; delta = cycles - lastCycles;
var khz = parseInt(delta/ms); var khz = parseInt(delta/ms);
$('#khz').text( khz + 'KHz'); document.querySelector('#khz').innerText = khz + 'KHz';
} }
startTime = now; startTime = now;
@ -473,13 +398,15 @@ function updateKHz() {
} }
window.updateSound = function updateSound() { window.updateSound = function updateSound() {
var on = $('#enable_sound').prop('checked'); var on = document.querySelector('#enable_sound').checked;
var label = $('#toggle-sound i'); var label = document.querySelector('#toggle-sound i');
audio.enable(on); audio.enable(on);
if (on) { if (on) {
label.removeClass('fa-volume-off').addClass('fa-volume-up'); label.classList.remove('fa-volume-off');
label.classList.add('fa-volume-up');
} else { } else {
label.removeClass('fa-volume-up').addClass('fa-volume-off'); label.classList.remove('fa-volume-up');
label.classList.add('fa-volume-off');
} }
}; };
@ -518,7 +445,7 @@ var accelerated = false;
window.updateCPU = function updateCPU() window.updateCPU = function updateCPU()
{ {
accelerated = $('#accelerator_toggle').prop('checked'); accelerated = document.querySelector('#accelerator_toggle').checked;
kHz = accelerated ? 4092 : 1023; kHz = accelerated ? 4092 : 1023;
io.updateHz(kHz * 1000); io.updateHz(kHz * 1000);
if (runTimer) { if (runTimer) {
@ -686,29 +613,31 @@ function loadBinary(bin) {
} }
window.selectCategory = function() { window.selectCategory = function() {
$('#disk_select').empty(); document.querySelector('#disk_select').innerHTML = '';
var cat = disk_categories[$('#category_select').val()]; var cat = disk_categories[document.querySelector('#category_select').value];
if (cat) { if (cat) {
for (var idx = 0; idx < cat.length; idx++) { for (var idx = 0; idx < cat.length; idx++) {
var file = cat[idx], name = file.name; var file = cat[idx], name = file.name;
if (file.disk) { if (file.disk) {
name += ' - ' + file.disk; name += ' - ' + file.disk;
} }
var option = $('<option />').val(file.filename).text(name) var option = document.createElement('option');
.appendTo('#disk_select'); option.value = file.filename;
option.innerText = name;
document.querySelector('#disk_select').append(option);
if (disk_cur_name[_currentDrive] == name) { if (disk_cur_name[_currentDrive] == name) {
option.attr('selected', 'selected'); option.selected = true;
} }
} }
} }
}; };
window.selectDisk = function() { window.selectDisk = function() {
$('#local_file').val(''); document.querySelector('#local_file').value = '';
}; };
window.clickDisk = function() { window.clickDisk = function() {
doLoad(); window.doLoad();
}; };
function loadDisk(drive, disk) { function loadDisk(drive, disk) {
@ -742,7 +671,7 @@ function updateLocalStorage() {
} }
cat = disk_categories['Local Saves'] = []; cat = disk_categories['Local Saves'] = [];
$('#manage').empty(); document.querySelector('#manage-modal-content').innerHTML = '';
names.forEach(function(name) { names.forEach(function(name) {
cat.push({ cat.push({
@ -750,13 +679,12 @@ function updateLocalStorage() {
'name': name, 'name': name,
'filename': 'local:' + name 'filename': 'local:' + name
}); });
$('#manage').append( document.querySelector('#manage-modal-content').innerHTML =
'<span class="local_save">' + '<span class="local_save">' +
name + name +
' <a href="#" onclick="doDelete(\'' + ' <a href="#" onclick="doDelete(\'' +
name + name +
'\')">Delete</a><br /></span>' '\')">Delete</a><br /></span>';
);
}); });
cat.push({ cat.push({
'category': 'Local Saves', 'category': 'Local Saves',
@ -832,9 +760,17 @@ function _keydown(evt) {
} }
if (evt.keyCode === 112) { // F1 - Reset if (evt.keyCode === 112) { // F1 - Reset
cpu.reset(); cpu.reset();
evt.preventDefault(); // prevent launching help
} else if (evt.keyCode === 113) { // F2 - Full Screen } else if (evt.keyCode === 113) { // F2 - Full Screen
var elem = document.getElementById('screen'); var elem = document.getElementById('screen');
if (document.webkitCancelFullScreen) { if (evt.shiftKey) { // Full window, but not full screen
document.querySelector('#display').classList.toggle('zoomwindow');
document.querySelector('#display > div').classList.toggle('overscan', 'flexbox-centering');
document.querySelector('#screen').classList.toggle('maxhw');
document.querySelector('#header').classList.toggle('hidden');
document.querySelector('.inset').classList.toggle('hidden');
document.querySelector('#reset').classList.toggle('hidden');
} else if (document.webkitCancelFullScreen) {
if (document.webkitIsFullScreen) { if (document.webkitIsFullScreen) {
document.webkitCancelFullScreen(); document.webkitCancelFullScreen();
} else { } else {
@ -876,8 +812,8 @@ function _keyup(evt) {
} }
window.updateScreen = function updateScreen() { window.updateScreen = function updateScreen() {
var green = $('#green_screen').prop('checked'); var green = document.querySelector('#green_screen').checked;
var scanlines = $('#show_scanlines').prop('checked'); var scanlines = document.querySelector('#show_scanlines').checked;
vm.green(green); vm.green(green);
vm.scanlines(scanlines); vm.scanlines(scanlines);
@ -889,10 +825,10 @@ var flipY = false;
var swapXY = false; var swapXY = false;
window.updateJoystick = function() { window.updateJoystick = function() {
disableMouseJoystick = $('#disable_mouse').prop('checked'); disableMouseJoystick = document.querySelector('#disable_mouse').checked;
flipX = $('#flip_x').prop('checked'); flipX = document.querySelector('#flip_x').checked;
flipY = $('#flip_y').prop('checked'); flipY = document.querySelector('#flip_y').checked;
swapXY = $('#swap_x_y').prop('checked'); swapXY = document.querySelector('#swap_x_y').checked;
configGamepad(flipX, flipY); configGamepad(flipX, flipY);
if (disableMouseJoystick) { if (disableMouseJoystick) {
@ -907,10 +843,10 @@ function _mousemove(evt) {
return; return;
} }
var s = $('#screen'); var s = document.querySelector('#screen');
var offset = s.offset(); var offset = { top: s.clientTop, left: s.clientLeft };
var x = (evt.pageX - offset.left) / s.width(), var x = (evt.pageX - offset.left) / s.clientWidth,
y = (evt.pageY - offset.top) / s.height(), y = (evt.pageY - offset.top) / s.clientHeight,
z = x; z = x;
if (swapXY) { if (swapXY) {
@ -923,79 +859,87 @@ function _mousemove(evt) {
} }
window.pauseRun = function() { window.pauseRun = function() {
var label = $('#pause-run i'); var label = document.querySelector('#pause-run i');
if (paused) { if (paused) {
run(); run();
label.removeClass('fa-play').addClass('fa-pause'); label.classList.remove('fa-play');
label.classList.add('fa-pause');
} else { } else {
stop(); stop();
label.removeClass('fa-pause').addClass('fa-play'); label.classList.remove('fa-pause');
label.classList.add('fa-play');
} }
paused = !paused; paused = !paused;
}; };
window.toggleSound = function() { window.toggleSound = function() {
var enableSound = $('#enable_sound'); var enableSound = document.querySelector('#enable_sound');
enableSound.prop('checked', !enableSound.prop('checked')); enableSound.checked = !enableSound.checked;
window.updateSound(); window.updateSound();
}; };
$(function() { window.openOptions = function () {
hashtag = document.location.hash; MicroModal.show('options-modal');
};
$('button,input[type=button],a.button').button().focus(function() { window.openPrinterModal = function () {
// Crazy hack required by Chrome MicroModal.show('printer-modal');
var self = this; };
window.setTimeout(function() {
self.blur(); MicroModal.init();
}, 1);
}); document.addEventListener('DOMContentLoaded', function() {
hashtag = document.location.hash;
/* /*
* Input Handling * Input Handling
*/ */
$(window) window.addEventListener('keydown', _keydown);
.keydown(_keydown) window.addEventListener('keyup', _keyup);
.keyup(_keyup) window.addEventListener('mousedown', function() { audio.autoStart(); });
.mousedown(function() { audio.autoStart(); });
$('canvas') document.querySelectorAll('canvas').forEach(function(canvas) {
.mousedown(function(evt) { canvas.addEventListener('mousedown', function(evt) {
if (!gamepad) { if (!gamepad) {
io.buttonDown(evt.which == 1 ? 0 : 1); io.buttonDown(evt.which == 1 ? 0 : 1);
} }
evt.preventDefault(); evt.preventDefault();
}) });
.mouseup(function(evt) { canvas.addEventListener('mouseup', function(evt) {
if (!gamepad) { if (!gamepad) {
io.buttonUp(evt.which == 1 ? 0 : 1); io.buttonUp(evt.which == 1 ? 0 : 1);
} }
}) });
.bind('contextmenu', function(evt) { evt.preventDefault(); }); });
$('body').mousemove(_mousemove); document.body.addEventListener('mousemove', _mousemove);
$('input,textarea') document.querySelectorAll('input,textarea').forEach(function(input) {
.focus(function() { focused = true; }) input.addEventListener('input', function() { focused = true; });
.blur(function() { focused = false; }); input.addEventListener('blur', function() { focused = false; });
});
keyboard.create('#keyboard'); keyboard.create('#keyboard');
if (prefs.havePrefs()) { if (prefs.havePrefs()) {
$('#options input[type=checkbox]').each(function() { document.querySelectorAll('#options-modal input[type=checkbox]').forEach(function(el) {
var val = prefs.readPref(this.id); var val = prefs.readPref(el.id);
if (val) if (val) {
this.checked = JSON.parse(val); el.checked = JSON.parse(val);
}).change(function() { }
prefs.writePref(this.id, JSON.stringify(this.checked)); el.addEventListener('change', function() {
prefs.writePref(el.id, JSON.stringify(el.checked));
});
}); });
$('#options select').each(function() { document.querySelectorAll('#options-modal select').forEach(function(el) {
var val = prefs.readPref(this.id); var val = prefs.readPref(el.id);
if (val) if (val) {
this.value = val; el.value = val;
}).change(function() { }
prefs.writePref(this.id, this.value); el.addEventListener('change', function() {
prefs.writePref(el.id, el.value);
});
}); });
} }
@ -1005,54 +949,12 @@ $(function() {
window.updateScreen(); window.updateScreen();
window.updateCPU(); window.updateCPU();
var cancel = function() { $(this).dialog('close'); };
$('#loading').dialog({ autoOpen: false, modal: true });
$('#options').dialog({
autoOpen: false,
modal: true,
width: 320,
buttons: {'Close': cancel }
});
$('#load').dialog({
autoOpen: false,
modal: true,
width: 540,
buttons: {'Cancel': cancel, 'Load': doLoad }
});
$('#save').dialog({
autoOpen: false,
modal: true,
width: 320,
buttons: {'Cancel': cancel, 'Save': doSave }
});
$('#manage').dialog({
autoOpen: false,
modal: true,
width: 320,
buttons: {'Close': cancel }
});
$('#printer').dialog({
autoOpen: false,
modal: true,
resizeable: false,
width: 570,
buttons: {
'Clear': printer.clear,
'Close': cancel
}
});
$('#http_load').dialog({
autoOpen: false,
modal: true,
width: 530,
buttons: {'Cancel': cancel, 'OK': doLoadHTTP }
});
if (window.localStorage !== undefined) { if (window.localStorage !== undefined) {
$('.disksave').show(); document.querySelectorAll('.disksave').forEach(function (el) { el.style.display = 'inline-block';});
} }
var oldcat = ''; var oldcat = '';
var option;
for (var idx = 0; idx < window.disk_index.length; idx++) { for (var idx = 0; idx < window.disk_index.length; idx++) {
var file = window.disk_index[idx]; var file = window.disk_index[idx];
var cat = file.category; var cat = file.category;
@ -1061,7 +963,11 @@ $(function() {
continue; continue;
} }
if (cat != oldcat) { if (cat != oldcat) {
$('<option />').val(cat).text(cat).appendTo('#category_select'); option = document.createElement('option');
option.value = cat;
option.innerText = cat;
document.querySelector('#category_select').append(option);
disk_categories[cat] = []; disk_categories[cat] = [];
oldcat = cat; oldcat = cat;
} }
@ -1073,7 +979,9 @@ $(function() {
disk_sets[name].push(file); disk_sets[name].push(file);
} }
} }
$('<option/>').text('Local Saves').appendTo('#category_select'); option = document.createElement('option');
option.innerText = 'Local Saves';
document.querySelector('#category_select').append(option);
updateLocalStorage(); updateLocalStorage();
initGamepad(); initGamepad();
@ -1085,23 +993,21 @@ $(function() {
processHash(hash); processHash(hash);
} }
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
$('select').removeAttr('multiple').css('height', 'auto');
}
if (navigator.standalone) { if (navigator.standalone) {
$('body').addClass('standalone'); document.body.classList.add('standalone');
} }
$('.key-REPT').click(function() { var reptKey = document.querySelector('.key-REPT');
$('#keyboard').hide(); reptKey.addEventListener('click', function() {
$('#textarea').show(); document.querySelector('#keyboard').style.display = 'none';
$('#text_input').focus(); document.querySelector('#textarea').style.display = 'block';
document.querySelector.focus();
}); });
$('#text_input').keydown(function() { document.querySelector('#text_input').addEventListener('keydown', function() {
focused = $('#buffering').prop('checked'); focused = document.querySelector('#buffering').checked;
}).keyup(function() { });
focused = $('#buffering').prop('checked'); document.querySelector('#text_input').addEventListener('keyup', function() {
focused = document.querySelector('#buffering').checked;
}); });
run(); run();

View File

@ -1,3 +1,5 @@
import MicroModal from 'micromodal';
import Apple2IO from './apple2io'; import Apple2IO from './apple2io';
import ApplesoftDump from './applesoft/decompiler'; import ApplesoftDump from './applesoft/decompiler';
import { HiresPage, LoresPage, VideoModes } from './canvas'; import { HiresPage, LoresPage, VideoModes } from './canvas';
@ -7,12 +9,13 @@ import Prefs from './prefs';
import { debug, gup, hup } from './util'; import { debug, gup, hup } from './util';
import Audio from './ui/audio'; import Audio from './ui/audio';
import DriveLights from './ui/drive_lights';
import { gamepad, configGamepad, initGamepad, processGamepad } from './ui/gamepad'; import { gamepad, configGamepad, initGamepad, processGamepad } from './ui/gamepad';
import KeyBoard from './ui/keyboard'; import KeyBoard from './ui/keyboard';
import Printer from './ui/printer'; import Printer from './ui/printer';
import Tape from './ui/tape'; import Tape, { TAPE_TYPES } from './ui/tape';
import DiskII from './cards/disk2'; import DiskII, { DISK_TYPES } from './cards/disk2';
import Parallel from './cards/parallel'; import Parallel from './cards/parallel';
import RAMFactor from './cards/ramfactor'; import RAMFactor from './cards/ramfactor';
import Thunderclock from './cards/thunderclock'; import Thunderclock from './cards/thunderclock';
@ -41,86 +44,11 @@ var TRACE = false;
var MAX_TRACE = 256; var MAX_TRACE = 256;
var trace = []; var trace = [];
/*
* Page viewer
*/
/*
function PageDebug(page)
{
var _page = page;
function _init() {
var r, c;
var row = $('<tr />').appendTo('#page' + toHex(_page));
$('<th>\\</th>').appendTo(row);
for (c = 0; c < 16; c++) {
$('<th>' + toHex(c) + '</th>').appendTo(row);
}
for (r = 0; r < 16; r++) {
row = $('<tr />').appendTo('#page' + toHex(_page));
$('<th>' + toHex(r * 16) + '</th>').appendTo(row);
for (c = 0; c < 16; c++) {
$('<td>--</td>').appendTo(row).attr('id', 'page' + toHex(_page) + '-' + toHex(r * 16 + c));
}
}
}
_init();
return {
start: function() { return _page; },
end: function() { return _page; },
read: null,
write: function(page, off, val) {
$('#page' + toHex(page) + '-' + toHex(off)).text(toHex(val));
}
};
}
*/
var disk_categories = {'Local Saves': []}; var disk_categories = {'Local Saves': []};
var disk_sets = {}; var disk_sets = {};
var disk_cur_name = []; var disk_cur_name = [];
var disk_cur_cat = []; var disk_cur_cat = [];
function DriveLights()
{
return {
driveLight: function(drive, on) {
$('#disk' + drive).css('background-image',
on ? 'url(css/red-on-16.png)' :
'url(css/red-off-16.png)');
},
dirty: function() {
// $('#disksave' + drive).button('option', 'disabled', !dirty);
},
label: function(drive, label) {
if (label) {
$('#disklabel' + drive).text(label);
}
return $('#disklabel' + drive).text();
},
getState: function() {
return {
disks: [
this.label(1),
this.label(2)
]
};
},
setState: function(state) {
if (state && state.disks) {
this.label(1, state.disks[0].label);
this.label(2, state.disks[1].label);
}
}
};
}
var DISK_TYPES = ['dsk','d13','do','po','raw','nib','2mg'];
var TAPE_TYPES = ['wav','aiff','aif','mp3','m4a'];
var _currentDrive = 1; var _currentDrive = 1;
window.openLoad = function(drive, event) window.openLoad = function(drive, event)
@ -130,9 +58,10 @@ window.openLoad = function(drive, event)
openLoadHTTP(drive); openLoadHTTP(drive);
} else { } else {
if (disk_cur_cat[drive]) { if (disk_cur_cat[drive]) {
$('#category_select').val(disk_cur_cat[drive]).change(); document.querySelector('#category_select').value = disk_cur_cat[drive];
window.selectCategory();
} }
$('#load').dialog('open'); MicroModal.show('load-modal');
} }
}; };
@ -142,17 +71,17 @@ window.openSave = function(drive, event)
var mimetype = 'application/octet-stream'; var mimetype = 'application/octet-stream';
var data = disk2.getBinary(drive); var data = disk2.getBinary(drive);
var a = $('#local_save_link'); var a = document.querySelector('#local_save_link');
var blob = new Blob([data], { 'type': mimetype }); var blob = new Blob([data], { 'type': mimetype });
a.attr('href', window.URL.createObjectURL(blob)); a.href = window.URL.createObjectURL(blob);
a.attr('download', drivelights.label(drive) + '.dsk'); a.download = drivelights.label(drive) + '.dsk';
if (event.metaKey) { if (event.metaKey) {
dumpDisk(drive); dumpDisk(drive);
} else { } else {
$('#save_name').val(drivelights.label(drive)); document.querySelector('#save_name').value = drivelights.label(drive);
$('#save').dialog('open'); MicroModal.show('save-modal');
} }
}; };
@ -191,6 +120,16 @@ window.handleDrop = function(drive, event) {
} else if (dt.files.length == 2) { } else if (dt.files.length == 2) {
doLoadLocal(1, dt.files[0]); doLoadLocal(1, dt.files[0]);
doLoadLocal(2, dt.files[1]); doLoadLocal(2, dt.files[1]);
} else {
for (var idx = 0; idx < dt.items.length; idx++) {
if (dt.items[idx].type === 'text/uri-list') {
dt.items[idx].getAsString(function(url) {
var parts = document.location.hash.split('|');
parts[drive - 1] = url;
document.location.hash = parts.join('|');
});
}
}
} }
}; };
@ -198,32 +137,29 @@ var loading = false;
function loadAjax(drive, url) { function loadAjax(drive, url) {
loading = true; loading = true;
$('#loading').dialog('open'); MicroModal.show('loading-modal');
$.ajax({ fetch(url).then(function(response) {
url: url, return response.json();
dataType: 'json', }).then(function(data) {
modifiedSince: true, if (data.type == 'binary') {
error: function(xhr, status, error) { loadBinary(drive, data);
alert(error || status); } else if (DISK_TYPES.includes(data.type)) {
$('#loading').dialog('close'); loadDisk(drive, data);
loading = false;
},
success: function(data) {
if (data.type == 'binary') {
loadBinary(drive, data);
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
loadDisk(drive, data);
}
initGamepad(data.gamepad);
$('#loading').dialog('close');
loading = false;
} }
initGamepad(data.gamepad);
MicroModal.close('loading-modal');
loading = false;
}).catch(function(error) {
window.alert(error || status);
MicroModal.close('loading-modal');
loading = false;
}); });
} }
function doLoad() { window.doLoad = function doLoad() {
var urls = $('#disk_select').val(), url; MicroModal.close('load-modal');
var urls = document.querySelector('#disk_select').value, url;
if (urls && urls.length) { if (urls && urls.length) {
if (typeof(urls) == 'string') { if (typeof(urls) == 'string') {
url = urls; url = urls;
@ -232,12 +168,12 @@ function doLoad() {
} }
} }
var files = $('#local_file').prop('files'); var files = document.querySelector('#local_file').files;
if (files.length == 1) { if (files.length == 1) {
doLoadLocal(_currentDrive, files[0]); doLoadLocal(_currentDrive, files[0]);
} else if (url) { } else if (url) {
var filename; var filename;
$('#load').dialog('close'); MicroModal.close('load-modal');
if (url.substr(0,6) == 'local:') { if (url.substr(0,6) == 'local:') {
filename = url.substr(6); filename = url.substr(6);
if (filename == '__manage') { if (filename == '__manage') {
@ -255,16 +191,15 @@ function doLoad() {
var parts = document.location.hash.split('|'); var parts = document.location.hash.split('|');
parts[_currentDrive - 1] = filename; parts[_currentDrive - 1] = filename;
document.location.hash = parts.join('|'); document.location.hash = parts.join('|');
loadAjax(_currentDrive, url);
} }
} }
} };
function doSave() { window.doSave = function doSave() {
var name = $('#save_name').val(); var name = document.querySelector('#save_name').value;
saveLocalStorage(_currentDrive, name); saveLocalStorage(_currentDrive, name);
$('#save').dialog('close'); MicroModal.close('save-modal');
} };
window.doDelete = function(name) { window.doDelete = function(name) {
if (window.confirm('Delete ' + name + '?')) { if (window.confirm('Delete ' + name + '?')) {
@ -275,15 +210,15 @@ window.doDelete = function(name) {
function doLoadLocal(drive, file) { function doLoadLocal(drive, file) {
var parts = file.name.split('.'); var parts = file.name.split('.');
var ext = parts[parts.length - 1].toLowerCase(); var ext = parts[parts.length - 1].toLowerCase();
if ($.inArray(ext, DISK_TYPES) >= 0) { if (DISK_TYPES.includes(ext)) {
doLoadLocalDisk(drive, file); doLoadLocalDisk(drive, file);
} else if ($.inArray(ext, TAPE_TYPES) >= 0) { } else if ($.inArray(ext, TAPE_TYPES) >= 0) {
tape.doLoadLocalTape(file, function() { tape.doLoadLocalTape(file, function() {
$('#load').dialog('close'); MicroModal.close('load-modal');
}); });
} else { } else {
window.alert('Unknown file type: ' + ext); window.alert('Unknown file type: ' + ext);
$('#load').dialog('close'); MicroModal.close('load-modal');
} }
} }
@ -295,7 +230,7 @@ function doLoadLocalDisk(drive, file) {
var name = parts.join('.'); var name = parts.join('.');
if (disk2.setBinary(drive, name, ext, this.result)) { if (disk2.setBinary(drive, name, ext, this.result)) {
drivelights.label(drive, name); drivelights.label(drive, name);
$('#load').dialog('close'); MicroModal.close('load-modal');
initGamepad(); initGamepad();
} }
}; };
@ -303,7 +238,7 @@ function doLoadLocalDisk(drive, file) {
} }
function doLoadHTTP(drive, _url) { function doLoadHTTP(drive, _url) {
var url = _url || $('#http_url').val(); var url = _url || document.querySelector('#http_url').value;
if (url) { if (url) {
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
req.open('GET', url, true); req.open('GET', url, true);
@ -317,7 +252,7 @@ function doLoadHTTP(drive, _url) {
var name = decodeURIComponent(fileParts.join('.')); var name = decodeURIComponent(fileParts.join('.'));
if (disk2.setBinary(drive, name, ext, req.response)) { if (disk2.setBinary(drive, name, ext, req.response)) {
drivelights.label(drive, name); drivelights.label(drive, name);
$('#http_load').dialog('close'); MicroModal.close('http-modal');
initGamepad(); initGamepad();
} }
}; };
@ -327,11 +262,11 @@ function doLoadHTTP(drive, _url) {
function openLoadHTTP(drive) { function openLoadHTTP(drive) {
_currentDrive = parseInt(drive, 10); _currentDrive = parseInt(drive, 10);
$('#http_load').dialog('open'); MicroModal.show('http-modal');
} }
function openManage() { function openManage() {
$('#manage').dialog('open'); MicroModal.show('manage-modal');
} }
var prefs = new Prefs(); var prefs = new Prefs();
@ -397,7 +332,7 @@ var io = new Apple2IO(cpu, vm);
var keyboard = new KeyBoard(cpu, io, true); var keyboard = new KeyBoard(cpu, io, true);
var audio = new Audio(io); var audio = new Audio(io);
var tape = new Tape(io); var tape = new Tape(io);
var printer = new Printer($('#printer .paper')); var printer = new Printer('#printer-modal .paper');
var mmu = new MMU(cpu, vm, gr, gr2, hgr, hgr2, io, rom); var mmu = new MMU(cpu, vm, gr, gr2, hgr, hgr2, io, rom);
@ -424,11 +359,11 @@ function updateKHz() {
if (window.showFPS) { if (window.showFPS) {
delta = renderedFrames - lastFrames; delta = renderedFrames - lastFrames;
var fps = parseInt(delta/(ms/1000), 10); var fps = parseInt(delta/(ms/1000), 10);
$('#khz').text( fps + 'fps'); document.querySelector('#khz').innerText = fps + 'fps';
} else { } else {
delta = cycles - lastCycles; delta = cycles - lastCycles;
var khz = parseInt(delta/ms); var khz = parseInt(delta/ms);
$('#khz').text( khz + 'KHz'); document.querySelector('#khz').innerText = khz + 'KHz';
} }
startTime = now; startTime = now;
@ -436,14 +371,16 @@ function updateKHz() {
lastFrames = renderedFrames; lastFrames = renderedFrames;
} }
window.updateSound = function() { window.updateSound = function updateSound() {
var on = $('#enable_sound').prop('checked'); var on = document.querySelector('#enable_sound').checked;
var label = $('#toggle-sound i'); var label = document.querySelector('#toggle-sound i');
audio.enable(on); audio.enable(on);
if (on) { if (on) {
label.removeClass('fa-volume-off').addClass('fa-volume-up'); label.classList.remove('fa-volume-off');
label.classList.add('fa-volume-up');
} else { } else {
label.removeClass('fa-volume-up').addClass('fa-volume-off'); label.classList.remove('fa-volume-up');
label.classList.add('fa-volume-off');
} }
}; };
@ -480,9 +417,9 @@ window.step = function()
var accelerated = false; var accelerated = false;
window.updateCPU = function() window.updateCPU = function updateCPU()
{ {
accelerated = $('#accelerator_toggle').prop('checked'); accelerated = document.querySelector('#accelerator_toggle').checked;
kHz = accelerated ? 4092 : 1023; kHz = accelerated ? 4092 : 1023;
io.updateHz(kHz * 1000); io.updateHz(kHz * 1000);
if (runTimer) { if (runTimer) {
@ -510,7 +447,6 @@ function run(pc) {
var now, last = Date.now(); var now, last = Date.now();
var runFn = function() { var runFn = function() {
now = Date.now(); now = Date.now();
renderedFrames++;
var step = (now - last) * kHz, stepMax = kHz * ival; var step = (now - last) * kHz, stepMax = kHz * ival;
last = now; last = now;
@ -543,7 +479,9 @@ function run(pc) {
} else { } else {
cpu.stepCycles(step); cpu.stepCycles(step);
} }
vm.blit(); if (vm.blit()) {
renderedFrames++;
}
io.tick(); io.tick();
} }
@ -635,29 +573,31 @@ function loadBinary(bin) {
} }
window.selectCategory = function() { window.selectCategory = function() {
$('#disk_select').empty(); document.querySelector('#disk_select').innerHTML = '';
var cat = disk_categories[$('#category_select').val()]; var cat = disk_categories[document.querySelector('#category_select').value];
if (cat) { if (cat) {
for (var idx = 0; idx < cat.length; idx++) { for (var idx = 0; idx < cat.length; idx++) {
var file = cat[idx], name = file.name; var file = cat[idx], name = file.name;
if (file.disk) { if (file.disk) {
name += ' - ' + file.disk; name += ' - ' + file.disk;
} }
var option = $('<option />').val(file.filename).text(name) var option = document.createElement('option');
.appendTo('#disk_select'); option.value = file.filename;
option.innerText = name;
document.querySelector('#disk_select').append(option);
if (disk_cur_name[_currentDrive] == name) { if (disk_cur_name[_currentDrive] == name) {
option.attr('selected', 'selected'); option.selected = true;
} }
} }
} }
}; };
window.selectDisk = function() { window.selectDisk = function() {
$('#local_file').val(''); document.querySelector('#local_file').value = '';
}; };
window.clickDisk = function() { window.clickDisk = function() {
doLoad(); window.doLoad();
}; };
function loadDisk(drive, disk) { function loadDisk(drive, disk) {
@ -691,7 +631,7 @@ function updateLocalStorage() {
} }
cat = disk_categories['Local Saves'] = []; cat = disk_categories['Local Saves'] = [];
$('#manage').empty(); document.querySelector('#manage-modal-content').innerHTML = '';
names.forEach(function(name) { names.forEach(function(name) {
cat.push({ cat.push({
@ -699,13 +639,12 @@ function updateLocalStorage() {
'name': name, 'name': name,
'filename': 'local:' + name 'filename': 'local:' + name
}); });
$('#manage').append( document.querySelector('#manage-modal-content').innerHTML =
'<span class="local_save">' + '<span class="local_save">' +
name + name +
' <a href="#" onclick="doDelete(\'' + ' <a href="#" onclick="doDelete(\'' +
name + name +
'\')">Delete</a><br /></span>' '\')">Delete</a><br /></span>';
);
}); });
cat.push({ cat.push({
'category': 'Local Saves', 'category': 'Local Saves',
@ -773,9 +712,7 @@ function processHash(hash) {
window.reset = keyboard.reset; window.reset = keyboard.reset;
function _keydown(evt) { function _keydown(evt) {
audio.autoStart(); if (!focused && (!evt.metaKey || evt.ctrlKey)) {
if (!focused) {
evt.preventDefault(); evt.preventDefault();
var key = keyboard.mapKeyEvent(evt); var key = keyboard.mapKeyEvent(evt);
@ -789,14 +726,12 @@ function _keydown(evt) {
} else if (evt.keyCode === 113) { // F2 - Full Screen } else if (evt.keyCode === 113) { // F2 - Full Screen
var elem = document.getElementById('screen'); var elem = document.getElementById('screen');
if (evt.shiftKey) { // Full window, but not full screen if (evt.shiftKey) { // Full window, but not full screen
$('#display').toggleClass('zoomwindow'); document.querySelector('#display').classList.toggle('zoomwindow');
$('#display > div') document.querySelector('#display > div').classList.toggle('overscan', 'flexbox-centering');
.toggleClass('overscan') document.querySelector('#screen').classList.toggle('maxhw');
.toggleClass('flexbox-centering'); document.querySelector('#header').classList.toggle('hidden');
$('#screen').toggleClass('maxhw'); document.querySelector('.inset').classList.toggle('hidden');
$('#header').toggleClass('hidden'); document.querySelector('#reset').classList.toggle('hidden');
$('.inset').toggleClass('hidden');
$('#reset').toggleClass('hidden');
} else if (document.webkitCancelFullScreen) { } else if (document.webkitCancelFullScreen) {
if (document.webkitIsFullScreen) { if (document.webkitIsFullScreen) {
document.webkitCancelFullScreen(); document.webkitCancelFullScreen();
@ -827,7 +762,7 @@ function _keydown(evt) {
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command } else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
keyboard.commandKey(true); keyboard.commandKey(true);
} else if (evt.keyCode == 18) { // Alt } else if (evt.keyCode == 18) { // Alt
if (evt.originalEvent.location == 1) { if (evt.location == 1) {
keyboard.commandKey(true); keyboard.commandKey(true);
} else { } else {
keyboard.optionKey(true); keyboard.optionKey(true);
@ -846,7 +781,7 @@ function _keyup(evt) {
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command } else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
keyboard.commandKey(false); keyboard.commandKey(false);
} else if (evt.keyCode == 18) { // Alt } else if (evt.keyCode == 18) { // Alt
if (evt.originalEvent.location == 1) { if (evt.location == 1) {
keyboard.commandKey(false); keyboard.commandKey(false);
} else { } else {
keyboard.optionKey(false); keyboard.optionKey(false);
@ -854,9 +789,9 @@ function _keyup(evt) {
} }
} }
window.updateScreen = function() { window.updateScreen = function updateScreen() {
var green = $('#green_screen').prop('checked'); var green = document.querySelector('#green_screen').checked;
var scanlines = $('#show_scanlines').prop('checked'); var scanlines = document.querySelector('#show_scanlines').checked;
vm.green(green); vm.green(green);
vm.scanlines(scanlines); vm.scanlines(scanlines);
@ -868,10 +803,10 @@ var flipY = false;
var swapXY = false; var swapXY = false;
window.updateJoystick = function() { window.updateJoystick = function() {
disableMouseJoystick = $('#disable_mouse').prop('checked'); disableMouseJoystick = document.querySelector('#disable_mouse').checked;
flipX = $('#flip_x').prop('checked'); flipX = document.querySelector('#flip_x').checked;
flipY = $('#flip_y').prop('checked'); flipY = document.querySelector('#flip_y').checked;
swapXY = $('#swap_x_y').prop('checked'); swapXY = document.querySelector('#swap_x_y').checked;
configGamepad(flipX, flipY); configGamepad(flipX, flipY);
if (disableMouseJoystick) { if (disableMouseJoystick) {
@ -886,10 +821,10 @@ function _mousemove(evt) {
return; return;
} }
var s = $('#screen'); var s = document.querySelector('#screen');
var offset = s.offset(); var offset = { top: s.clientTop, left: s.clientLeft };
var x = (evt.pageX - offset.left) / s.width(), var x = (evt.pageX - offset.left) / s.clientWidth,
y = (evt.pageY - offset.top) / s.height(), y = (evt.pageY - offset.top) / s.clientHeight,
z = x; z = x;
if (swapXY) { if (swapXY) {
@ -902,79 +837,87 @@ function _mousemove(evt) {
} }
window.pauseRun = function() { window.pauseRun = function() {
var label = $('#pause-run i'); var label = document.querySelector('#pause-run i');
if (paused) { if (paused) {
run(); run();
label.removeClass('fa-play').addClass('fa-pause'); label.classList.remove('fa-play');
label.classList.add('fa-pause');
} else { } else {
stop(); stop();
label.removeClass('fa-pause').addClass('fa-play'); label.classList.remove('fa-pause');
label.classList.add('fa-play');
} }
paused = !paused; paused = !paused;
}; };
window.toggleSound = function() { window.toggleSound = function() {
var enableSound = $('#enable_sound'); var enableSound = document.querySelector('#enable_sound');
enableSound.prop('checked', !enableSound.prop('checked')); enableSound.checked = !enableSound.checked;
window.updateSound(); window.updateSound();
}; };
$(function() { window.openOptions = function () {
hashtag = document.location.hash; MicroModal.show('options-modal');
};
$('button,input[type=button],a.button').button().focus(function() { window.openPrinterModal = function () {
// Crazy hack required by Chrome MicroModal.show('printer-modal');
var self = this; };
window.setTimeout(function() {
self.blur(); MicroModal.init();
}, 1);
}); document.addEventListener('DOMContentLoaded', function() {
hashtag = document.location.hash;
/* /*
* Input Handling * Input Handling
*/ */
$(window) window.addEventListener('keydown', _keydown);
.keydown(_keydown) window.addEventListener('keyup', _keyup);
.keyup(_keyup) window.addEventListener('mousedown', function() { audio.autoStart(); });
.mousedown(function() { audio.autoStart(); });
$('canvas') document.querySelectorAll('canvas').forEach(function(canvas) {
.mousedown(function(evt) { canvas.addEventListener('mousedown', function(evt) {
if (!gamepad) { if (!gamepad) {
io.buttonDown(evt.which == 1 ? 0 : 1); io.buttonDown(evt.which == 1 ? 0 : 1);
} }
evt.preventDefault(); evt.preventDefault();
}) });
.mouseup(function(evt) { canvas.addEventListener('mouseup', function(evt) {
if (!gamepad) { if (!gamepad) {
io.buttonUp(evt.which == 1 ? 0 : 1); io.buttonUp(evt.which == 1 ? 0 : 1);
} }
}) });
.bind('contextmenu', function(evt) { evt.preventDefault(); }); });
$('body').mousemove(_mousemove); document.body.addEventListener('mousemove', _mousemove);
$('input,textarea') document.querySelectorAll('input,textarea').forEach(function(input) {
.focus(function() { focused = true; }) input.addEventListener('input', function() { focused = true; });
.blur(function() { focused = false; }); input.addEventListener('blur', function() { focused = false; });
});
keyboard.create('#keyboard'); keyboard.create('#keyboard');
if (prefs.havePrefs()) { if (prefs.havePrefs()) {
$('#options input[type=checkbox]').each(function() { document.querySelectorAll('#options-modal input[type=checkbox]').forEach(function(el) {
var val = prefs.readPref(this.id); var val = prefs.readPref(el.id);
if (val) if (val) {
this.checked = JSON.parse(val); el.checked = JSON.parse(val);
}).change(function() { }
prefs.writePref(this.id, JSON.stringify(this.checked)); el.addEventListener('change', function() {
prefs.writePref(el.id, JSON.stringify(el.checked));
});
}); });
$('#options select').each(function() { document.querySelectorAll('#options-modal select').forEach(function(el) {
var val = prefs.readPref(this.id); var val = prefs.readPref(el.id);
if (val) if (val) {
this.value = val; el.value = val;
}).change(function() { }
prefs.writePref(this.id, this.value); el.addEventListener('change', function() {
prefs.writePref(el.id, el.value);
});
}); });
} }
@ -984,60 +927,22 @@ $(function() {
window.updateScreen(); window.updateScreen();
window.updateCPU(); window.updateCPU();
var cancel = function() { $(this).dialog('close'); };
$('#loading').dialog({ autoOpen: false, modal: true });
$('#options').dialog({
autoOpen: false,
modal: true,
width: 320,
buttons: {'Close': cancel }
});
$('#load').dialog({
autoOpen: false,
modal: true,
width: 540,
buttons: {'Cancel': cancel, 'Load': doLoad }
});
$('#save').dialog({
autoOpen: false,
modal: true,
width: 320,
buttons: {'Cancel': cancel, 'Save': doSave }
});
$('#manage').dialog({
autoOpen: false,
modal: true,
width: 320,
buttons: {'Close': cancel }
});
$('#printer').dialog({
autoOpen: false,
modal: true,
resizeable: false,
width: 570,
buttons: {
'Clear': printer.clear,
'Close': cancel
}
});
$('#http_load').dialog({
autoOpen: false,
modal: true,
width: 530,
buttons: {'Cancel': cancel, 'OK': doLoadHTTP }
});
if (window.localStorage !== undefined) { if (window.localStorage !== undefined) {
$('.disksave').show(); document.querySelectorAll('.disksave').forEach(function (el) { el.style.display = 'inline-block';});
} }
var oldcat = ''; var oldcat = '';
var option;
for (var idx = 0; idx < window.disk_index.length; idx++) { for (var idx = 0; idx < window.disk_index.length; idx++) {
var file = window.disk_index[idx]; var file = window.disk_index[idx];
var cat = file.category; var cat = file.category;
var name = file.name, disk = file.disk; var name = file.name, disk = file.disk;
if (cat != oldcat) { if (cat != oldcat) {
$('<option />').val(cat).text(cat).appendTo('#category_select'); option = document.createElement('option');
option.value = cat;
option.innerText = cat;
document.querySelector('#category_select').append(option);
disk_categories[cat] = []; disk_categories[cat] = [];
oldcat = cat; oldcat = cat;
} }
@ -1049,7 +954,9 @@ $(function() {
disk_sets[name].push(file); disk_sets[name].push(file);
} }
} }
$('<option/>').text('Local Saves').appendTo('#category_select'); option = document.createElement('option');
option.innerText = 'Local Saves';
document.querySelector('#category_select').append(option);
updateLocalStorage(); updateLocalStorage();
initGamepad(); initGamepad();
@ -1061,12 +968,8 @@ $(function() {
processHash(hash); processHash(hash);
} }
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
$('select').removeAttr('multiple').css('height', 'auto');
}
if (navigator.standalone) { if (navigator.standalone) {
$('body').addClass('standalone'); document.body.classList.add('standalone');
} }
run(); run();

34
js/ui/drive_lights.js Normal file
View File

@ -0,0 +1,34 @@
export default function DriveLights()
{
return {
driveLight: function(drive, on) {
var disk = document.querySelector('#disk' + drive);
disk.style.backgroundImage =
on ? 'url(css/red-on-16.png)' :
'url(css/red-off-16.png)';
},
dirty: function() {
// document.querySelector('#disksave' + drive).disabled = !dirty;
},
label: function(drive, label) {
if (label) {
document.querySelector('#disklabel' + drive).innerText = label;
}
return document.querySelector('#disklabel' + drive).innerText;
},
getState: function() {
return {
disks: [
this.label(1),
this.label(2)
]
};
},
setState: function(state) {
if (state && state.disks) {
this.label(1, state.disks[0].label);
this.label(2, state.disks[1].label);
}
}
};
}

View File

@ -106,7 +106,8 @@ export function initGamepad(data) {
gamepadMap[idx] = undefined; gamepadMap[idx] = undefined;
} }
var map = data || DEFAULT_GAMEPAD; var map = data || DEFAULT_GAMEPAD;
$.each(map, function(key, val) { Object.keys(map).forEach(function(key) {
var val = map[key];
if (typeof val == 'string') { if (typeof val == 'string') {
val = val.charCodeAt(0); val = val.charCodeAt(0);
} else { } else {

View File

@ -213,7 +213,7 @@ export default function KeyBoard(cpu, io, e) {
} else if (code in keymap) { } else if (code in keymap) {
key = keymap[code][evt.shiftKey ? 2 : (evt.ctrlKey ? 1 : 0)]; key = keymap[code][evt.shiftKey ? 2 : (evt.ctrlKey ? 1 : 0)];
if (capslocked && key >= 0x61 && key <= 0x7A) if (capslocked && key >= 0x61 && key <= 0x7A)
key -= '\x20'; key -= 0x20;
} else { } else {
debug('Unhandled key = ' + toHex(code)); debug('Unhandled key = ' + toHex(code));
} }

View File

@ -9,12 +9,15 @@
* implied warranty. * implied warranty.
*/ */
export default function Printer(paper) { export default function Printer(el) {
var _lineBuffer; var paper = document.querySelector(el);
var _lineBuffer = '';
var _line; var _line;
function newLine() { function newLine() {
_line = $('<div>').addClass('line').text(_lineBuffer); _line = document.createElement('div');
_line.classList.add('line');
_line.innerText = _lineBuffer;
paper.append(_line); paper.append(_line);
_lineBuffer = ''; _lineBuffer = '';
} }
@ -29,7 +32,8 @@ export default function Printer(paper) {
if (c == '\r') { if (c == '\r') {
newLine(); newLine();
_lineBuffer = ''; } else if (c == '\n') {
// eat for now
} else if (c == '\t') { } else if (c == '\t') {
_lineBuffer += ' '; _lineBuffer += ' ';
} else if (c == 0x04) { } else if (c == 0x04) {
@ -39,7 +43,7 @@ export default function Printer(paper) {
_lineBuffer += c; _lineBuffer += c;
} }
} }
_line.text(_lineBuffer); _line.innerText = _lineBuffer;
}, },
clear: function() { clear: function() {
@ -49,7 +53,7 @@ export default function Printer(paper) {
}, },
hasPrintout: function() { hasPrintout: function() {
return paper.text().length(); return paper.text.length;
} }
}; };
} }

View File

@ -12,6 +12,8 @@
import { debug } from '../util'; import { debug } from '../util';
export const TAPE_TYPES = ['wav','aiff','aif','mp3','m4a'];
export default function Tape(io) { export default function Tape(io) {
var AudioContext = window.AudioContext || window.webkitAudioContext; var AudioContext = window.AudioContext || window.webkitAudioContext;

5
package-lock.json generated
View File

@ -3515,6 +3515,11 @@
"to-regex": "^3.0.2" "to-regex": "^3.0.2"
} }
}, },
"micromodal": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/micromodal/-/micromodal-0.3.2.tgz",
"integrity": "sha512-xRON1OqD9G8FfI1qShYTtJZaN77x03QR2UnkpL7H17877lATNJoV8XHR+nrnc2FqgXqjFdaYJYidbfISecMlNQ=="
},
"miller-rabin": { "miller-rabin": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",

View File

@ -24,5 +24,8 @@
"webpack": "^4.29.6", "webpack": "^4.29.6",
"webpack-cli": "^3.2.3", "webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.2.1" "webpack-dev-server": "^3.2.1"
},
"dependencies": {
"micromodal": "^0.3.2"
} }
} }