ipad mouse buttons, keyboard refactoring

This commit is contained in:
Devaev Maxim 2019-04-24 22:32:53 +03:00
parent 3ecd337b3a
commit 3d64401b11
9 changed files with 558 additions and 437 deletions

View File

@ -6,6 +6,7 @@ globals:
Msd: true
Session: true
Streamer: true
Keypad: true
WindowManager: true
wm: true
tools: true

View File

@ -43,6 +43,7 @@
<link rel="stylesheet" href="../share/css/sliders.css">
<link rel="stylesheet" href="../share/css/switches.css">
<link rel="stylesheet" href="../share/css/progress.css">
<link rel="stylesheet" href="../share/css/keypad.css">
<link rel="stylesheet" href="../share/css/kvm/stream.css">
<link rel="stylesheet" href="../share/css/kvm/hid.css">
<link rel="stylesheet" href="../share/css/kvm/msd.css">
@ -52,6 +53,7 @@
<script src="../share/js/bb.js"></script>
<script src="../share/js/tools.js"></script>
<script src="../share/js/wm.js"></script>
<script src="../share/js/keypad.js"></script>
<script src="../share/js/kvm/stream.js"></script>
<script src="../share/js/kvm/atx.js"></script>
<script src="../share/js/kvm/keyboard.js"></script>
@ -306,9 +308,16 @@
<div id="stream-box" class="stream-box-inactive">
<img id="stream-image" class="stream-image-inactive" src="../share/png/blank-stream.png" />
</div>
<div id="stream-mouse-buttons" class="buttons-row">
<button data-mouse-button="left" class="row50">Left Click</button>
<button data-mouse-button="right" class="row50">Right Click</button>
<div id="stream-mouse-buttons" class="keypad" align="center">
<div class="keypad-block">
<div class="keypad-row">
<div data-code="left" class="key wide-4 left small"><p>Mouse<br>Left</p></div>
<div data-code="left" class="modifier wide-2 left small"><p><b>&bull;</b><br>&larr; Hold</p></div>
<div class="empty-key" style="width:10px"></div>
<div data-code="right" class="modifier wide-2 right small"><p><b>&bull;</b><br>Hold &rarr;</p></div>
<div data-code="right" class="key wide-4 right small"><p>Mouse<br>Right</p></div>
</div>
</div>
</div>
</div>
@ -317,231 +326,231 @@
<div class="window-grab">Virtual Keyboard</div>
<button class="window-button-close">&times;</button>
</div>
<div id="keyboard-desktop" class="keyboard" align="center">
<div class="keyboard-block">
<div class="keyboard-row">
<div data-key="Escape" class="key small"><p>Esc</p></div>
<div id="keyboard-desktop" class="keypad" align="center">
<div class="keypad-block">
<div class="keypad-row">
<div data-code="Escape" class="key small"><p>Esc</p></div>
<div class="empty-key" style="width:24px"></div>
<div data-key="F1" class="key small"><p>F1</p></div>
<div data-key="F2" class="key small"><p>F2</p></div>
<div data-key="F3" class="key small"><p>F3</p></div>
<div data-key="F4" class="key small"><p>F4</p></div>
<div data-code="F1" class="key small"><p>F1</p></div>
<div data-code="F2" class="key small"><p>F2</p></div>
<div data-code="F3" class="key small"><p>F3</p></div>
<div data-code="F4" class="key small"><p>F4</p></div>
<div class="empty-key" style="width:10px"></div>
<div data-key="F5" class="key small"><p>F5</p></div>
<div data-key="F6" class="key small"><p>F6</p></div>
<div data-key="F7" class="key small"><p>F7</p></div>
<div data-key="F8" class="key small"><p>F8</p></div>
<div data-code="F5" class="key small"><p>F5</p></div>
<div data-code="F6" class="key small"><p>F6</p></div>
<div data-code="F7" class="key small"><p>F7</p></div>
<div data-code="F8" class="key small"><p>F8</p></div>
<div class="empty-key" style="width:10px"></div>
<div data-key="F9" class="key small"><p>F9</p></div>
<div data-key="F10" class="key small"><p>F10</p></div>
<div data-key="F11" class="key small"><p>F11</p></div>
<div data-key="F12" class="key small"><p>F12</p></div>
<div data-code="F9" class="key small"><p>F9</p></div>
<div data-code="F10" class="key small"><p>F10</p></div>
<div data-code="F11" class="key small"><p>F11</p></div>
<div data-code="F12" class="key small"><p>F12</p></div>
</div>
<hr>
<div class="keyboard-row">
<div data-key="Backquote" class="key"><p>~<br>`</p></div>
<div data-key="Digit1" class="key"><p>!<br>1</p></div>
<div data-key="Digit2" class="key"><p>@<br>2</p></div>
<div data-key="Digit3" class="key"><p>#<br>3</p></div>
<div data-key="Digit4" class="key"><p>$<br>4</p></div>
<div data-key="Digit5" class="key"><p>%<br>5</p></div>
<div data-key="Digit6" class="key"><p>^<br>6</p></div>
<div data-key="Digit7" class="key"><p>&amp;<br>7</p></div>
<div data-key="Digit8" class="key"><p>*<br>8</p></div>
<div data-key="Digit9" class="key"><p>(<br>9</p></div>
<div data-key="Digit0" class="key"><p>)<br>0</p></div>
<div data-key="Minus" class="key"><p>_<br>-</p></div>
<div data-key="Equal" class="key"><p>+<br>=</p></div>
<div data-key="Backspace" class="key wide-2 right"><p>&#8612;</p></div>
<div class="keypad-row">
<div data-code="Backquote" class="key"><p>~<br>`</p></div>
<div data-code="Digit1" class="key"><p>!<br>1</p></div>
<div data-code="Digit2" class="key"><p>@<br>2</p></div>
<div data-code="Digit3" class="key"><p>#<br>3</p></div>
<div data-code="Digit4" class="key"><p>$<br>4</p></div>
<div data-code="Digit5" class="key"><p>%<br>5</p></div>
<div data-code="Digit6" class="key"><p>^<br>6</p></div>
<div data-code="Digit7" class="key"><p>&amp;<br>7</p></div>
<div data-code="Digit8" class="key"><p>*<br>8</p></div>
<div data-code="Digit9" class="key"><p>(<br>9</p></div>
<div data-code="Digit0" class="key"><p>)<br>0</p></div>
<div data-code="Minus" class="key"><p>_<br>-</p></div>
<div data-code="Equal" class="key"><p>+<br>=</p></div>
<div data-code="Backspace" class="key wide-2 right"><p>&#8612;</p></div>
</div>
<div class="keyboard-row">
<div data-key="Tab" class="key wide-2 left"><p>&#8676;<br>&#8677;</p></div>
<div data-key="KeyQ" class="key single"><p>Q</p></div>
<div data-key="KeyW" class="key single"><p>W</p></div>
<div data-key="KeyE" class="key single"><p>E</p></div>
<div data-key="KeyR" class="key single"><p>R</p></div>
<div data-key="KeyT" class="key single"><p>T</p></div>
<div data-key="KeyY" class="key single"><p>Y</p></div>
<div data-key="KeyU" class="key single"><p>U</p></div>
<div data-key="KeyI" class="key single"><p>I</p></div>
<div data-key="KeyO" class="key single"><p>O</p></div>
<div data-key="KeyP" class="key single"><p>P</p></div>
<div data-key="BracketLeft" class="key"><p>{<br>[</p></div>
<div data-key="BracketRight" class="key"><p>}<br>]</p></div>
<div data-key="Backslash" class="key"><p>|<br>\</p></div>
<div class="keypad-row">
<div data-code="Tab" class="key wide-2 left"><p>&#8676;<br>&#8677;</p></div>
<div data-code="KeyQ" class="key single"><p>Q</p></div>
<div data-code="KeyW" class="key single"><p>W</p></div>
<div data-code="KeyE" class="key single"><p>E</p></div>
<div data-code="KeyR" class="key single"><p>R</p></div>
<div data-code="KeyT" class="key single"><p>T</p></div>
<div data-code="KeyY" class="key single"><p>Y</p></div>
<div data-code="KeyU" class="key single"><p>U</p></div>
<div data-code="KeyI" class="key single"><p>I</p></div>
<div data-code="KeyO" class="key single"><p>O</p></div>
<div data-code="KeyP" class="key single"><p>P</p></div>
<div data-code="BracketLeft" class="key"><p>{<br>[</p></div>
<div data-code="BracketRight" class="key"><p>}<br>]</p></div>
<div data-code="Backslash" class="key"><p>|<br>\</p></div>
</div>
<div class="keyboard-row">
<div data-key="CapsLock" class="key wide-3 left small"><p>Caps Lock</p></div>
<div data-key="KeyA" class="key single"><p>A</p></div>
<div data-key="KeyS" class="key single"><p>S</p></div>
<div data-key="KeyD" class="key single"><p>D</p></div>
<div data-key="KeyF" class="key single"><p>F</p></div>
<div data-key="KeyG" class="key single"><p>G</p></div>
<div data-key="KeyH" class="key single"><p>H</p></div>
<div data-key="KeyJ" class="key single"><p>J</p></div>
<div data-key="KeyK" class="key single"><p>K</p></div>
<div data-key="KeyL" class="key single"><p>L</p></div>
<div data-key="Semicolon" class="key"><p>:<br>;</p></div>
<div data-key="Quote" class="key"><p>"<br>'</p></div>
<div data-key="Enter" class="key wide-3 right small"><p>Enter<br>&crarr;</p></div>
<div class="keypad-row">
<div data-code="CapsLock" class="key wide-3 left small"><p>Caps Lock</p></div>
<div data-code="KeyA" class="key single"><p>A</p></div>
<div data-code="KeyS" class="key single"><p>S</p></div>
<div data-code="KeyD" class="key single"><p>D</p></div>
<div data-code="KeyF" class="key single"><p>F</p></div>
<div data-code="KeyG" class="key single"><p>G</p></div>
<div data-code="KeyH" class="key single"><p>H</p></div>
<div data-code="KeyJ" class="key single"><p>J</p></div>
<div data-code="KeyK" class="key single"><p>K</p></div>
<div data-code="KeyL" class="key single"><p>L</p></div>
<div data-code="Semicolon" class="key"><p>:<br>;</p></div>
<div data-code="Quote" class="key"><p>"<br>'</p></div>
<div data-code="Enter" class="key wide-3 right small"><p>Enter<br>&crarr;</p></div>
</div>
<div class="keyboard-row">
<div data-key="ShiftLeft" class="modifier wide-4 left small"><p><b>&bull;</b><br>Shift</p></div>
<div data-key="KeyZ" class="key single"><p>Z</p></div>
<div data-key="KeyX" class="key single"><p>X</p></div>
<div data-key="KeyC" class="key single"><p>C</p></div>
<div data-key="KeyV" class="key single"><p>V</p></div>
<div data-key="KeyB" class="key single"><p>B</p></div>
<div data-key="KeyN" class="key single"><p>N</p></div>
<div data-key="KeyM" class="key single"><p>M</p></div>
<div data-key="Comma" class="key"><p>&lt;<br>,</p></div>
<div data-key="Period" class="key"><p>&gt;<br>.</p></div>
<div data-key="Slash" class="key"><p>?<br>/</p></div>
<div data-key="ShiftRight" class="modifier wide-4 right small"><p><b>&bull;</b><br>Shift</p></div>
<div class="keypad-row">
<div data-code="ShiftLeft" class="modifier wide-4 left small"><p><b>&bull;</b><br>Shift</p></div>
<div data-code="KeyZ" class="key single"><p>Z</p></div>
<div data-code="KeyX" class="key single"><p>X</p></div>
<div data-code="KeyC" class="key single"><p>C</p></div>
<div data-code="KeyV" class="key single"><p>V</p></div>
<div data-code="KeyB" class="key single"><p>B</p></div>
<div data-code="KeyN" class="key single"><p>N</p></div>
<div data-code="KeyM" class="key single"><p>M</p></div>
<div data-code="Comma" class="key"><p>&lt;<br>,</p></div>
<div data-code="Period" class="key"><p>&gt;<br>.</p></div>
<div data-code="Slash" class="key"><p>?<br>/</p></div>
<div data-code="ShiftRight" class="modifier wide-4 right small"><p><b>&bull;</b><br>Shift</p></div>
</div>
<div class="keyboard-row">
<div data-key="ControlLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Ctrl</p></div>
<div data-key="MetaLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Win</p></div>
<div data-key="AltLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Alt</p></div>
<div data-key="Space" class="key wide-5"></div>
<div data-key="AltRight" class="modifier wide-1 right small"><p><b>&bull;</b><br>Alt</p></div>
<div data-key="MetaRight" class="modifier wide-1 right small"><p><b>&bull;</b><br>Win</p></div>
<div data-key="ControlRight" class="modifier wide-1 right small"><p><b>&bull;</b><br>Ctrl</p></div>
<div class="keypad-row">
<div data-code="ControlLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Ctrl</p></div>
<div data-code="MetaLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Win</p></div>
<div data-code="AltLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Alt</p></div>
<div data-code="Space" class="key wide-5"></div>
<div data-code="AltRight" class="modifier wide-1 right small"><p><b>&bull;</b><br>Alt</p></div>
<div data-code="MetaRight" class="modifier wide-1 right small"><p><b>&bull;</b><br>Win</p></div>
<div data-code="ControlRight" class="modifier wide-1 right small"><p><b>&bull;</b><br>Ctrl</p></div>
</div>
</div>
<div class="keyboard-block">
<div class="keyboard-row">
<div data-key="PrintScreen" class="modifier small"><p><b>&bull;</b><br>Pt/Sq</p></div>
<div data-key="ScrollLock" class="key small"><p>ScrLk</p></div>
<div data-key="Pause" class="key small"><p>P/Brk</p></div>
<div class="keypad-block">
<div class="keypad-row">
<div data-code="PrintScreen" class="modifier small"><p><b>&bull;</b><br>Pt/Sq</p></div>
<div data-code="ScrollLock" class="key small"><p>ScrLk</p></div>
<div data-code="Pause" class="key small"><p>P/Brk</p></div>
</div>
<hr>
<div class="keyboard-row">
<div data-key="Insert" class="key small"><p>Ins</p></div>
<div data-key="Home" class="key small"><p>Home</p></div>
<div data-key="PageUp" class="key small"><p>PgUp</p></div>
<div class="keypad-row">
<div data-code="Insert" class="key small"><p>Ins</p></div>
<div data-code="Home" class="key small"><p>Home</p></div>
<div data-code="PageUp" class="key small"><p>PgUp</p></div>
</div>
<div class="keyboard-row">
<div data-key="Delete" class="key small"><p>Del</p></div>
<div data-key="End" class="key small"><p>End</p></div>
<div data-key="PageDown" class="key small"><p>PgDn</p></div>
<div class="keypad-row">
<div data-code="Delete" class="key small"><p>Del</p></div>
<div data-code="End" class="key small"><p>End</p></div>
<div data-code="PageDown" class="key small"><p>PgDn</p></div>
</div>
<div class="keyboard-row"></div>
<div class="keyboard-row">
<div class="keypad-row"></div>
<div class="keypad-row">
<div class="empty-key"></div>
<div data-key="ArrowUp" class="key"><p>&uarr;</p></div>
<div data-code="ArrowUp" class="key"><p>&uarr;</p></div>
<div class="empty-key"></div>
</div>
<div class="keyboard-row">
<div data-key="ArrowLeft" class="key"><p>&larr;</p></div>
<div data-key="ArrowDown" class="key"><p>&darr;</p></div>
<div data-key="ArrowRight" class="key"><p>&rarr;</p></div>
<div class="keypad-row">
<div data-code="ArrowLeft" class="key"><p>&larr;</p></div>
<div data-code="ArrowDown" class="key"><p>&darr;</p></div>
<div data-code="ArrowRight" class="key"><p>&rarr;</p></div>
</div>
</div>
</div>
<div id="keyboard-mobile" class="keyboard" align="center">
<div class="keyboard-block">
<div class="keyboard-row">
<div data-key="Escape" class="key margin-0 small"><p>Esc</p></div>
<div id="keyboard-mobile" class="keypad" align="center">
<div class="keypad-block">
<div class="keypad-row">
<div data-code="Escape" class="key margin-0 small"><p>Esc</p></div>
<div class="empty-key" style="width:4px"></div>
<div data-key="F1" class="key wide-0 margin-0 small"><p>F1</p></div>
<div data-key="F2" class="key wide-0 margin-0 small"><p>F2</p></div>
<div data-key="F3" class="key wide-0 margin-0 small"><p>F3</p></div>
<div data-key="F4" class="key wide-0 margin-0 small"><p>F4</p></div>
<div data-key="F5" class="key wide-0 margin-0 small"><p>F5</p></div>
<div data-key="F6" class="key wide-0 margin-0 small"><p>F6</p></div>
<div data-key="F7" class="key wide-0 margin-0 small"><p>F7</p></div>
<div data-key="F8" class="key wide-0 margin-0 small"><p>F8</p></div>
<div data-key="F9" class="key wide-0 margin-0 small"><p>F9</p></div>
<div data-key="F10" class="key wide-0 margin-0 small"><p>F10</p></div>
<div data-key="F11" class="key wide-0 margin-0 small"><p>F11</p></div>
<div data-key="F12" class="key wide-0 margin-0 small"><p>F12</p></div>
<div data-code="F1" class="key wide-0 margin-0 small"><p>F1</p></div>
<div data-code="F2" class="key wide-0 margin-0 small"><p>F2</p></div>
<div data-code="F3" class="key wide-0 margin-0 small"><p>F3</p></div>
<div data-code="F4" class="key wide-0 margin-0 small"><p>F4</p></div>
<div data-code="F5" class="key wide-0 margin-0 small"><p>F5</p></div>
<div data-code="F6" class="key wide-0 margin-0 small"><p>F6</p></div>
<div data-code="F7" class="key wide-0 margin-0 small"><p>F7</p></div>
<div data-code="F8" class="key wide-0 margin-0 small"><p>F8</p></div>
<div data-code="F9" class="key wide-0 margin-0 small"><p>F9</p></div>
<div data-code="F10" class="key wide-0 margin-0 small"><p>F10</p></div>
<div data-code="F11" class="key wide-0 margin-0 small"><p>F11</p></div>
<div data-code="F12" class="key wide-0 margin-0 small"><p>F12</p></div>
<div class="empty-key" style="width:5px"></div>
<div data-key="PrintScreen" class="modifier margin-0 small"><p><b>&bull;</b><br>Pt/Sq</p></div>
<div data-key="ScrollLock" class="key margin-0 small"><p>ScrLk</p></div>
<div data-key="Pause" class="key margin-0 small"><p>P/Brk</p></div>
<div data-key="Insert" class="key margin-0 small"><p>Ins</p></div>
<div data-key="Home" class="key margin-0 small"><p>Home</p></div>
<div data-key="End" class="key margin-0 small"><p>End</p></div>
<div data-key="Delete" class="key margin-0 small"><p>Del</p></div>
<div data-code="PrintScreen" class="modifier margin-0 small"><p><b>&bull;</b><br>Pt/Sq</p></div>
<div data-code="ScrollLock" class="key margin-0 small"><p>ScrLk</p></div>
<div data-code="Pause" class="key margin-0 small"><p>P/Brk</p></div>
<div data-code="Insert" class="key margin-0 small"><p>Ins</p></div>
<div data-code="Home" class="key margin-0 small"><p>Home</p></div>
<div data-code="End" class="key margin-0 small"><p>End</p></div>
<div data-code="Delete" class="key margin-0 small"><p>Del</p></div>
</div>
<hr>
<div class="keyboard-row">
<div data-key="Backquote" class="key"><p>~<br>`</p></div>
<div data-key="Digit1" class="key"><p>!<br>1</p></div>
<div data-key="Digit2" class="key"><p>@<br>2</p></div>
<div data-key="Digit3" class="key"><p>#<br>3</p></div>
<div data-key="Digit4" class="key"><p>$<br>4</p></div>
<div data-key="Digit5" class="key"><p>%<br>5</p></div>
<div data-key="Digit6" class="key"><p>^<br>6</p></div>
<div data-key="Digit7" class="key"><p>&amp;<br>7</p></div>
<div data-key="Digit8" class="key"><p>*<br>8</p></div>
<div data-key="Digit9" class="key"><p>(<br>9</p></div>
<div data-key="Digit0" class="key"><p>)<br>0</p></div>
<div data-key="Minus" class="key"><p>_<br>-</p></div>
<div data-key="Equal" class="key"><p>+<br>=</p></div>
<div data-key="Backspace" class="key wide-3 right" style="width:101px"><p>&#8612;</p></div>
<div class="keypad-row">
<div data-code="Backquote" class="key"><p>~<br>`</p></div>
<div data-code="Digit1" class="key"><p>!<br>1</p></div>
<div data-code="Digit2" class="key"><p>@<br>2</p></div>
<div data-code="Digit3" class="key"><p>#<br>3</p></div>
<div data-code="Digit4" class="key"><p>$<br>4</p></div>
<div data-code="Digit5" class="key"><p>%<br>5</p></div>
<div data-code="Digit6" class="key"><p>^<br>6</p></div>
<div data-code="Digit7" class="key"><p>&amp;<br>7</p></div>
<div data-code="Digit8" class="key"><p>*<br>8</p></div>
<div data-code="Digit9" class="key"><p>(<br>9</p></div>
<div data-code="Digit0" class="key"><p>)<br>0</p></div>
<div data-code="Minus" class="key"><p>_<br>-</p></div>
<div data-code="Equal" class="key"><p>+<br>=</p></div>
<div data-code="Backspace" class="key wide-3 right" style="width:101px"><p>&#8612;</p></div>
</div>
<div class="keyboard-row">
<div data-key="Tab" class="key wide-2 left"><p>&#8676;<br>&#8677;</p></div>
<div data-key="KeyQ" class="key single"><p>Q</p></div>
<div data-key="KeyW" class="key single"><p>W</p></div>
<div data-key="KeyE" class="key single"><p>E</p></div>
<div data-key="KeyR" class="key single"><p>R</p></div>
<div data-key="KeyT" class="key single"><p>T</p></div>
<div data-key="KeyY" class="key single"><p>Y</p></div>
<div data-key="KeyU" class="key single"><p>U</p></div>
<div data-key="KeyI" class="key single"><p>I</p></div>
<div data-key="KeyO" class="key single"><p>O</p></div>
<div data-key="KeyP" class="key single"><p>P</p></div>
<div data-key="BracketLeft" class="key"><p>{<br>[</p></div>
<div data-key="BracketRight" class="key"><p>}<br>]</p></div>
<div data-key="Backslash" class="key wide-2 left" style="width:78px"><p>|<br>\</p></div>
<div class="keypad-row">
<div data-code="Tab" class="key wide-2 left"><p>&#8676;<br>&#8677;</p></div>
<div data-code="KeyQ" class="key single"><p>Q</p></div>
<div data-code="KeyW" class="key single"><p>W</p></div>
<div data-code="KeyE" class="key single"><p>E</p></div>
<div data-code="KeyR" class="key single"><p>R</p></div>
<div data-code="KeyT" class="key single"><p>T</p></div>
<div data-code="KeyY" class="key single"><p>Y</p></div>
<div data-code="KeyU" class="key single"><p>U</p></div>
<div data-code="KeyI" class="key single"><p>I</p></div>
<div data-code="KeyO" class="key single"><p>O</p></div>
<div data-code="KeyP" class="key single"><p>P</p></div>
<div data-code="BracketLeft" class="key"><p>{<br>[</p></div>
<div data-code="BracketRight" class="key"><p>}<br>]</p></div>
<div data-code="Backslash" class="key wide-2 left" style="width:78px"><p>|<br>\</p></div>
</div>
<div class="keyboard-row">
<div data-key="CapsLock" class="key wide-3 left small"><p>Caps Lock</p></div>
<div data-key="KeyA" class="key single"><p>A</p></div>
<div data-key="KeyS" class="key single"><p>S</p></div>
<div data-key="KeyD" class="key single"><p>D</p></div>
<div data-key="KeyF" class="key single"><p>F</p></div>
<div data-key="KeyG" class="key single"><p>G</p></div>
<div data-key="KeyH" class="key single"><p>H</p></div>
<div data-key="KeyJ" class="key single"><p>J</p></div>
<div data-key="KeyK" class="key single"><p>K</p></div>
<div data-key="KeyL" class="key single"><p>L</p></div>
<div data-key="Semicolon" class="key"><p>:<br>;</p></div>
<div data-key="Quote" class="key"><p>"<br>'</p></div>
<div data-key="Enter" class="key wide-4 right small" style="width:116px"><p>Enter<br>&crarr;</p></div>
<div class="keypad-row">
<div data-code="CapsLock" class="key wide-3 left small"><p>Caps Lock</p></div>
<div data-code="KeyA" class="key single"><p>A</p></div>
<div data-code="KeyS" class="key single"><p>S</p></div>
<div data-code="KeyD" class="key single"><p>D</p></div>
<div data-code="KeyF" class="key single"><p>F</p></div>
<div data-code="KeyG" class="key single"><p>G</p></div>
<div data-code="KeyH" class="key single"><p>H</p></div>
<div data-code="KeyJ" class="key single"><p>J</p></div>
<div data-code="KeyK" class="key single"><p>K</p></div>
<div data-code="KeyL" class="key single"><p>L</p></div>
<div data-code="Semicolon" class="key"><p>:<br>;</p></div>
<div data-code="Quote" class="key"><p>"<br>'</p></div>
<div data-code="Enter" class="key wide-4 right small" style="width:116px"><p>Enter<br>&crarr;</p></div>
</div>
<div class="keyboard-row">
<div data-key="ShiftLeft" class="modifier wide-4 left small"><p><b>&bull;</b><br>Shift</p></div>
<div data-key="KeyZ" class="key single"><p>Z</p></div>
<div data-key="KeyX" class="key single"><p>X</p></div>
<div data-key="KeyC" class="key single"><p>C</p></div>
<div data-key="KeyV" class="key single"><p>V</p></div>
<div data-key="KeyB" class="key single"><p>B</p></div>
<div data-key="KeyN" class="key single"><p>N</p></div>
<div data-key="KeyM" class="key single"><p>M</p></div>
<div data-key="Comma" class="key"><p>&lt;<br>,</p></div>
<div data-key="Period" class="key"><p>&gt;<br>.</p></div>
<div data-key="Slash" class="key"><p>?<br>/</p></div>
<div data-key="PageUp" class="key small"><p>PgUp</p></div>
<div data-key="ArrowUp" class="key"><p>&uarr;</p></div>
<div data-key="PageDown" class="key small"><p>PgDn</p></div>
<div class="keypad-row">
<div data-code="ShiftLeft" class="modifier wide-4 left small"><p><b>&bull;</b><br>Shift</p></div>
<div data-code="KeyZ" class="key single"><p>Z</p></div>
<div data-code="KeyX" class="key single"><p>X</p></div>
<div data-code="KeyC" class="key single"><p>C</p></div>
<div data-code="KeyV" class="key single"><p>V</p></div>
<div data-code="KeyB" class="key single"><p>B</p></div>
<div data-code="KeyN" class="key single"><p>N</p></div>
<div data-code="KeyM" class="key single"><p>M</p></div>
<div data-code="Comma" class="key"><p>&lt;<br>,</p></div>
<div data-code="Period" class="key"><p>&gt;<br>.</p></div>
<div data-code="Slash" class="key"><p>?<br>/</p></div>
<div data-code="PageUp" class="key small"><p>PgUp</p></div>
<div data-code="ArrowUp" class="key"><p>&uarr;</p></div>
<div data-code="PageDown" class="key small"><p>PgDn</p></div>
</div>
<div class="keyboard-row">
<div data-key="ControlLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Ctrl</p></div>
<div data-key="MetaLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Win</p></div>
<div data-key="AltLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Alt</p></div>
<div data-key="Space" class="key" style="width:190px"></div>
<div data-key="AltRight" class="modifier right small"><p><b>&bull;</b><br>Alt</p></div>
<div data-key="MetaRight" class="modifier right small"><p><b>&bull;</b><br>Win</p></div>
<div data-key="ShiftRight" class="modifier right small"><p><b>&bull;</b><br>Shift</p></div>
<div data-key="ControlRight" class="modifier right small"><p><b>&bull;</b><br>Ctrl</p></div>
<div data-key="ArrowLeft" class="key"><p>&larr;</p></div>
<div data-key="ArrowDown" class="key"><p>&darr;</p></div>
<div data-key="ArrowRight" class="key"><p>&rarr;</p></div>
<div class="keypad-row">
<div data-code="ControlLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Ctrl</p></div>
<div data-code="MetaLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Win</p></div>
<div data-code="AltLeft" class="modifier wide-1 left small"><p><b>&bull;</b><br>Alt</p></div>
<div data-code="Space" class="key" style="width:190px"></div>
<div data-code="AltRight" class="modifier right small"><p><b>&bull;</b><br>Alt</p></div>
<div data-code="MetaRight" class="modifier right small"><p><b>&bull;</b><br>Win</p></div>
<div data-code="ShiftRight" class="modifier right small"><p><b>&bull;</b><br>Shift</p></div>
<div data-code="ControlRight" class="modifier right small"><p><b>&bull;</b><br>Ctrl</p></div>
<div data-code="ArrowLeft" class="key"><p>&larr;</p></div>
<div data-code="ArrowDown" class="key"><p>&darr;</p></div>
<div data-code="ArrowRight" class="key"><p>&rarr;</p></div>
</div>
</div>
</div>

134
web/share/css/keypad.css Normal file
View File

@ -0,0 +1,134 @@
/*****************************************************************************
# #
# KVMD - The main Pi-KVM daemon. #
# #
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
# #
*****************************************************************************/
div.keypad {
zoom: 0.8;
}
div.keypad div.keypad-block {
display: table-cell;
padding-right: 0;
}
div.keypad div.keypad-block:not(:first-child) {
padding-left: 15px;
}
div.keypad div.keypad-row {
white-space: nowrap;
height: 40px;
margin-bottom: 5px;
}
div.keypad div.keypad-row:last-child {
margin-bottom: 0;
}
div.keypad div.key, div.modifier, div.empty-key {
box-sizing: border-box;
display: inline-block;
margin-right: 5px;
padding: 0;
width: 40px;
}
div.keypad div.key, div.modifier {
font-size: 0.9em;
text-align: center;
vertical-align: top;
box-shadow: var(--shadow-micro);
border: var(--border-key-thin);
border-radius: 6px;
color: var(--cs-key-default-fg);
background-color: var(--cs-key-default-bg);
cursor: pointer;
height: 40px;
}
div.keypad div.key:hover, div.modifier:hover {
color: var(--cs-key-hovered-fg);
background-color: var(--cs-key-hovered-bg);
}
div.keypad div.pressed {
box-shadow: none;
color: var(--cs-key-pressed-fg) !important;
background-color: var(--cs-key-pressed-bg) !important;
}
div.keypad div.holded {
box-shadow: none;
color: var(--cs-key-default-fg) !important;
background-color: var(--cs-key-holded-bg) !important;
}
div.keypad div.key:last-child, div.empty-key:last-child, div.modifier:last-child {
margin-right: 0;
}
div.keypad div.margin-0 {
margin-right: 0px;
}
div.keypad div.wide-0 {
width: 26px;
}
div.keypad div.wide-1 {
width: 61px;
}
div.keypad div.wide-2 {
width: 64px;
}
div.keypad div.wide-3 {
width: 77px;
}
div.keypad div.wide-4 {
width: 102px;
}
div.keypad div.wide-5 {
width: 288px;
}
div.keypad div.left {
text-align: left !important;
padding-left: 6px !important;
}
div.keypad div.right {
text-align: right !important;
padding-right: 6px !important;
}
div.keypad div.small {
font-size: 0.7em;
}
div.keypad p {
margin: 0;
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}
div.keypad b {
color: var(--cs-key-holded-bg);
}
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
/* iPad */
div.keypad {
zoom: 1.28 !important;
}
div.keypad div.key:hover, div.modifier:hover {
color: var(--cs-key-default-fg);
background-color: var(--cs-key-default-bg);
}
}

View File

@ -20,107 +20,6 @@
*****************************************************************************/
div.keyboard {
zoom: 0.8;
}
div.keyboard div.keyboard-block {
display: table-cell;
padding-right: 0;
}
div.keyboard div.keyboard-block:not(:first-child) {
padding-left: 15px;
}
div.keyboard div.keyboard-row {
white-space: nowrap;
height: 40px;
margin-bottom: 5px;
}
div.keyboard div.keyboard-row:last-child {
margin-bottom: 0;
}
div.keyboard div.key, div.modifier, div.empty-key {
box-sizing: border-box;
display: inline-block;
margin-right: 5px;
padding: 0;
width: 40px;
}
div.keyboard div.key, div.modifier {
font-size: 0.9em;
text-align: center;
vertical-align: top;
box-shadow: var(--shadow-micro);
border: var(--border-key-thin);
border-radius: 6px;
color: var(--cs-key-default-fg);
background-color: var(--cs-key-default-bg);
cursor: pointer;
height: 40px;
}
div.keyboard div.key:hover, div.modifier:hover {
color: var(--cs-key-hovered-fg);
background-color: var(--cs-key-hovered-bg);
}
div.keyboard div.pressed {
box-shadow: none;
color: var(--cs-key-pressed-fg) !important;
background-color: var(--cs-key-pressed-bg) !important;
}
div.keyboard div.holded {
box-shadow: none;
color: var(--cs-key-default-fg) !important;
background-color: var(--cs-key-holded-bg) !important;
}
div.keyboard div.key:last-child, div.empty-key:last-child, div.modifier:last-child {
margin-right: 0;
}
div.keyboard div.margin-0 {
margin-right: 0px;
}
div.keyboard div.wide-0 {
width: 26px;
}
div.keyboard div.wide-1 {
width: 61px;
}
div.keyboard div.wide-2 {
width: 64px;
}
div.keyboard div.wide-3 {
width: 77px;
}
div.keyboard div.wide-4 {
width: 102px;
}
div.keyboard div.wide-5 {
width: 288px;
}
div.keyboard div.left {
text-align: left !important;
padding-left: 6px !important;
}
div.keyboard div.right {
text-align: right !important;
padding-right: 6px !important;
}
div.keyboard div.small {
font-size: 0.7em;
}
div.keyboard p {
margin: 0;
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}
div.keyboard b {
color: var(--cs-key-holded-bg);
}
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
div#keyboard-window {
visibility: visible !important;
@ -149,16 +48,6 @@ div#keyboard-mobile {
display: none;
}
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
/* iPad */
div.keyboard {
zoom: 1.28 !important;
}
div.keyboard div.key:hover, div.modifier:hover {
color: var(--cs-key-default-fg);
background-color: var(--cs-key-default-bg);
}
div#keyboard-desktop {
display: none !important;
}

175
web/share/js/keypad.js Normal file
View File

@ -0,0 +1,175 @@
/*****************************************************************************
# #
# KVMD - The main Pi-KVM daemon. #
# #
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
# #
*****************************************************************************/
function Keypad(keys_parent, key_callback) {
var self = this;
/************************************************************************/
var __merged = {};
var __keys = {};
var __modifiers = {};
var __init__ = function() {
var code;
var el_key;
for (el_key of $$$(keys_parent + " div.key")) {
code = el_key.getAttribute("data-code");
tools.setDefault(__keys, code, []);
__keys[code].push(el_key);
tools.setDefault(__merged, code, []);
__merged[code].push(el_key);
(function(el_key) {
tools.setOnDown(el_key, () => __clickHandler(el_key, true));
tools.setOnUp(el_key, () => __clickHandler(el_key, false));
el_key.onmouseout = function() {
if (__isPressed(el_key)) {
__clickHandler(el_key, false);
}
};
})(el_key);
}
for (el_key of $$$(keys_parent + " div.modifier")) {
code = el_key.getAttribute("data-code");
tools.setDefault(__modifiers, code, []);
__modifiers[code].push(el_key);
tools.setDefault(__merged, code, []);
__merged[code].push(el_key);
(function(el_key) {
tools.setOnDown(el_key, () => __toggleModifierHandler(el_key));
})(el_key);
}
};
/************************************************************************/
self.releaseAll = function(release_hook=false) {
for (var dict of [__keys, __modifiers]) {
for (var code in dict) {
if (__isActive(dict[code][0])) {
self.emit(code, false, release_hook);
}
}
}
};
self.emit = function(code, state, release_hook=false) {
if (code in __merged) {
__commonHandler(__merged[code][0], state, false);
if (release_hook) {
for (code in __keys) {
if (__isActive(__keys[code][0])) {
self.emit(code, false);
}
}
}
__unholdModifiers();
}
};
var __clickHandler = function(el_key, state) {
__commonHandler(el_key, state, false);
__unholdModifiers();
};
var __toggleModifierHandler = function(el_key) {
__commonHandler(el_key, !__isActive(el_key), true);
};
var __commonHandler = function(el_key, state, hold) {
if (state && !__isActive(el_key)) {
__deactivate(el_key);
__activate(el_key, (hold ? "holded" : "pressed"));
__process(el_key, true);
} else {
__deactivate(el_key);
__process(el_key, false);
}
};
var __unholdModifiers = function() {
for (var code in __modifiers) {
var el_key = __modifiers[code][0];
if (__isHolded(el_key)) {
__deactivate(el_key);
__process(el_key, false);
}
}
};
var __isPressed = function(el_key) {
var is_pressed = false;
for (el_key of __resolveKeys(el_key)) {
is_pressed = (is_pressed || el_key.classList.contains("pressed"));
}
return is_pressed;
};
var __isHolded = function(el_key) {
var is_holded = false;
for (el_key of __resolveKeys(el_key)) {
is_holded = (is_holded || el_key.classList.contains("holded"));
}
return is_holded;
};
var __isActive = function(el_key) {
var is_active = false;
for (el_key of __resolveKeys(el_key)) {
is_active = (is_active || el_key.classList.contains("pressed") || el_key.classList.contains("holded"));
}
return is_active;
};
var __activate = function(el_key, cls) {
for (el_key of __resolveKeys(el_key)) {
el_key.classList.add(cls);
}
};
var __deactivate = function(el_key) {
for (el_key of __resolveKeys(el_key)) {
el_key.classList.remove("pressed");
el_key.classList.remove("holded");
}
};
var __resolveKeys = function(el_key) {
var code = el_key.getAttribute("data-code");
return __merged[code];
};
var __process = function(el_key, state) {
var code = el_key.getAttribute("data-code");
key_callback(code, state);
};
__init__();
}

View File

@ -91,6 +91,7 @@ function Hid() {
var __releaseAll = function() {
__keyboard.releaseAll();
__mouse.releaseAll();
};
var __emitShortcut = function(codes) {
@ -107,7 +108,7 @@ function Hid() {
var index = 0;
var iterate = () => setTimeout(function() {
__keyboard.fireEvent(raw_events[index].code, raw_events[index].state);
__keyboard.emit(raw_events[index].code, raw_events[index].state);
++index;
if (index < raw_events.length) {
iterate();

View File

@ -28,10 +28,12 @@ function Keyboard() {
var __ws = null;
var __online = true;
var __keys = [].slice.call($$$("div#keyboard-desktop div.keyboard-block div.keyboard-row div.key"));
var __modifiers = [].slice.call($$$("div#keyboard-desktop div.keyboard-block div.keyboard-row div.modifier"));
var __keypad = null;
var __use_release_hook = false;
var __init__ = function() {
__keypad = new Keypad("div#keyboard-window", __sendKey);
$("hid-keyboard-led").title = "Keyboard free";
$("keyboard-window").onkeydown = (event) => __keyboardHandler(event, true);
@ -47,22 +49,11 @@ function Keyboard() {
window.addEventListener("focusin", __updateLeds);
window.addEventListener("focusout", __updateLeds);
tools.forEach($$("key"), function(el_key) {
tools.setOnDown(el_key, () => __clickHandler(el_key, true));
tools.setOnUp(el_key, () => __clickHandler(el_key, false));
el_key.onmouseout = function() {
if (__isPressed(el_key)) {
__clickHandler(el_key, false);
}
};
});
tools.forEach($$("modifier"), function(el_key) {
tools.setOnDown(el_key, () => __toggleModifierHandler(el_key));
});
if (tools.browser.is_mac) {
// https://bugs.chromium.org/p/chromium/issues/detail?id=28089
// https://bugzilla.mozilla.org/show_bug.cgi?id=1299553
tools.info("Keyboard: enabled Mac-CMD-Hook");
__use_release_hook = true;
}
};
@ -82,14 +73,10 @@ function Keyboard() {
};
self.releaseAll = function() {
__keys.concat(__modifiers).forEach(function(el_key) {
if (__isActive(el_key)) {
self.fireEvent(el_key.getAttribute("data-key"), false);
}
});
__keypad.releaseAll(__use_release_hook);
};
self.fireEvent = function(code, state) {
self.emit = function(code, state) {
__keyboardHandler({code: code}, state);
};
@ -124,97 +111,14 @@ function Keyboard() {
if (event.preventDefault) {
event.preventDefault();
}
var el_key = document.querySelector(`[data-key='${event.code}']`);
if (el_key && !event.repeat) {
__commonHandler(el_key, state, "pressed");
if (tools.browser.is_mac) {
// https://bugs.chromium.org/p/chromium/issues/detail?id=28089
// https://bugzilla.mozilla.org/show_bug.cgi?id=1299553
if ((event.code === "MetaLeft" || event.code === "MetaRight") && !state) {
__keys.forEach(function(el_key) {
if (__isActive(el_key)) {
self.fireEvent(el_key.getAttribute("data-key"), false);
}
});
}
}
__unholdModifiers();
if (!event.repeat) {
// https://bugs.chromium.org/p/chromium/issues/detail?id=28089
// https://bugzilla.mozilla.org/show_bug.cgi?id=1299553
__keypad.emit(event.code, state, __use_release_hook);
}
};
var __clickHandler = function(el_key, state) {
__commonHandler(el_key, state, "pressed");
__unholdModifiers();
};
var __toggleModifierHandler = function(el_key) {
__commonHandler(el_key, !__isActive(el_key), "holded");
};
var __unholdModifiers = function() {
__modifiers.forEach(function(el_key) {
if (__isHolded(el_key)) {
__deactivate(el_key);
__sendKey(el_key, false);
}
});
};
var __commonHandler = function(el_key, state, cls) {
if (state && !__isActive(el_key)) {
__deactivate(el_key);
__activate(el_key, cls);
__sendKey(el_key, true);
} else {
__deactivate(el_key);
__sendKey(el_key, false);
}
};
var __isPressed = function(el_key) {
var is_pressed = false;
tools.forEach(__resolveKeys(el_key), function(el_key) {
is_pressed = (is_pressed || el_key.classList.contains("pressed"));
});
return is_pressed;
};
var __isHolded = function(el_key) {
var is_holded = false;
tools.forEach(__resolveKeys(el_key), function(el_key) {
is_holded = (is_holded || el_key.classList.contains("holded"));
});
return is_holded;
};
var __isActive = function(el_key) {
var is_active = false;
tools.forEach(__resolveKeys(el_key), function(el_key) {
is_active = (is_active || el_key.classList.contains("pressed") || el_key.classList.contains("holded"));
});
return is_active;
};
var __activate = function(el_key, cls) {
tools.forEach(__resolveKeys(el_key), function(el_key) {
el_key.classList.add(cls);
});
};
var __deactivate = function(el_key) {
tools.forEach(__resolveKeys(el_key), function(el_key) {
el_key.classList.remove("pressed");
el_key.classList.remove("holded");
});
};
var __resolveKeys = function(el_key) {
var code = el_key.getAttribute("data-key");
return $$$(`[data-key='${code}']`);
};
var __sendKey = function(el_key, state) {
var code = el_key.getAttribute("data-key");
var __sendKey = function(code, state) {
tools.debug("Keyboard: key", (state ? "pressed:" : "released:"), code);
if (__ws) {
__ws.send(JSON.stringify({

View File

@ -28,6 +28,8 @@ function Mouse() {
var __ws = null;
var __online = true;
var __keypad = null;
var __current_pos = {x: 0, y:0};
var __sent_pos = {x: 0, y:0};
var __wheel_delta = {x: 0, y: 0};
@ -35,22 +37,18 @@ function Mouse() {
var __stream_hovered = false;
var __init__ = function() {
__keypad = new Keypad("div#stream-mouse-buttons", __sendButton);
$("hid-mouse-led").title = "Mouse free";
$("stream-box").onmouseenter = __hoverStream;
$("stream-box").onmouseleave = __leaveStream;
$("stream-box").onmousedown = (event) => __buttonHandler(event, true);
$("stream-box").onmouseup = (event) => __buttonHandler(event, false);
$("stream-box").onmousedown = (event) => __streamButtonHandler(event, true);
$("stream-box").onmouseup = (event) => __streamButtonHandler(event, false);
$("stream-box").oncontextmenu = (event) => event.preventDefault();
$("stream-box").onmousemove = __moveHandler;
$("stream-box").onwheel = __wheelHandler;
$("stream-box").ontouchstart = (event) => __touchMoveHandler(event);
tools.forEach($$$("[data-mouse-button]"), function(el_button) {
var button = el_button.getAttribute("data-mouse-button");
tools.setOnDown(el_button, () => __sendButton(button, true));
tools.setOnUp(el_button, () => __sendButton(button, false));
});
$("stream-box").onmousemove = __streamMoveHandler;
$("stream-box").onwheel = __streamWheelHandler;
$("stream-box").ontouchstart = (event) => __streamTouchMoveHandler(event);
setInterval(__sendMove, 100);
};
@ -72,6 +70,10 @@ function Mouse() {
__updateLeds();
};
self.releaseAll = function() {
__keypad.releaseAll();
};
var __hoverStream = function() {
__stream_hovered = true;
__updateLeds();
@ -106,16 +108,16 @@ function Mouse() {
$("hid-mouse-led").title = title;
};
var __buttonHandler = function(event, state) {
var __streamButtonHandler = function(event, state) {
// https://www.w3schools.com/jsref/event_button.asp
event.preventDefault();
switch (event.button) {
case 0: __sendButton("left", state); break;
case 2: __sendButton("right", state); break;
case 0: __keypad.emit("left", state); break;
case 2: __keypad.emit("right", state); break;
}
};
var __touchMoveHandler = function(event) {
var __streamTouchMoveHandler = function(event) {
event.preventDefault();
if (event.touches[0].target && event.touches[0].target.getBoundingClientRect) {
var rect = event.touches[0].target.getBoundingClientRect();
@ -127,7 +129,7 @@ function Mouse() {
}
};
var __moveHandler = function(event) {
var __streamMoveHandler = function(event) {
var rect = event.target.getBoundingClientRect();
__current_pos = {
x: Math.round(event.clientX - rect.left),
@ -172,7 +174,7 @@ function Mouse() {
return Math.round((x - a) / (b - a) * (d - c) + c);
};
var __wheelHandler = function(event) {
var __streamWheelHandler = function(event) {
// https://learn.javascript.ru/mousewheel
if (event.preventDefault) {
event.preventDefault();

View File

@ -25,6 +25,12 @@ var tools = new function() {
this.forEach = (...args) => Array.prototype.forEach.call(...args);
this.setDefault = function(dict, key, value) {
if (!(key in dict)) {
dict[key] = value;
}
};
this.makeRequest = function(method, url, callback, body=null, content_type=null) {
var http = new XMLHttpRequest();
http.open(method, url, true);