Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • EzTunes/EECS498-uBoard
1 result
Show changes
Commits on Source (31)
Showing
with 2 additions and 42021 deletions
public/vendor/
node_modules/
custom_configs/*
dist/
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>16A323</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>uBoard</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>gif</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/gif</string>
</array>
<key>CFBundleTypeName</key>
<string>GIF image</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>GIFf</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>html</string>
<string>htm</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>text/html</string>
</array>
<key>CFBundleTypeName</key>
<string>HTML document</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>HTML</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>xhtml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>text/xhtml</string>
</array>
<key>CFBundleTypeName</key>
<string>XHTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>js</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/x-javascript</string>
</array>
<key>CFBundleTypeName</key>
<string>JavaScript script</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>jpg</string>
<string>jpeg</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/jpeg</string>
</array>
<key>CFBundleTypeName</key>
<string>JPEG image</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>JPEG</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>mhtml</string>
<string>mht</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>multipart/related</string>
<string>application/x-mimearchive</string>
<string>message/rfc822</string>
</array>
<key>CFBundleTypeName</key>
<string>MHTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>oga</string>
<string>ogg</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>audio/ogg</string>
</array>
<key>CFBundleTypeName</key>
<string>HTML5 Audio (Ogg)</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>ogv</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>video/ogg</string>
</array>
<key>CFBundleTypeName</key>
<string>HTML5 Video (Ogg)</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>png</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/png</string>
</array>
<key>CFBundleTypeName</key>
<string>PNG image</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>PNGf</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>svg</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/svg+xml</string>
</array>
<key>CFBundleTypeName</key>
<string>SVG document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>txt</string>
<string>text</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>text/plain</string>
</array>
<key>CFBundleTypeName</key>
<string>Plain text document</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>TEXT</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>webm</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>video/webm</string>
</array>
<key>CFBundleTypeName</key>
<string>HTML5 Video (WebM)</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>webp</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/webp</string>
</array>
<key>CFBundleTypeName</key>
<string>WebP image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>org.chromium.extension</string>
</array>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>pdf</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/pdf</string>
</array>
<key>CFBundleTypeName</key>
<string>PDF Document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>nwjs</string>
<key>CFBundleIconFile</key>
<string>app.icns</string>
<key>CFBundleIdentifier</key>
<string>io.github.nwjs.uBoard</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>uBoard</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>NWJS</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Web site URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
<string>https</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>FTP site URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ftp</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>Local file URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>file</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTSDKBuild</key>
<string>10.12</string>
<key>DTSDKName</key>
<string>macosx10.12</string>
<key>DTXcode</key>
<string>0833</string>
<key>DTXcodeBuild</key>
<string>8E3004b</string>
<key>LSFileQuarantineEnabled</key>
<true/>
<key>LSHasLocalizedDisplayName</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>10.9.0</string>
<key>NSAppleScriptEnabled</key>
<true/>
<key>NSPrincipalClass</key>
<string>BrowserCrApplication</string>
<key>NSSupportsAppNap</key>
<true/>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>NSUserActivityTypes</key>
<array>
<string>NSUserActivityTypeBrowsingWeb</string>
</array>
<key>NSUserNotificationAlertStyle</key>
<string>banner</string>
<key>OSAScriptingDefinition</key>
<string>scripting.sdef</string>
<key>SCMRevision</key>
<string>80813d9b281c182503bcedca446fee5ad785cd4f-</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>NWJS Extra</string>
<key>UTTypeIdentifier</key>
<string>org.chromium.extension</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>crx</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>
\ No newline at end of file
File deleted
APPLNWJS
\ No newline at end of file
CFBundleDisplayName = "uBoard";
CFBundleGetInfoString = "1.0.0";
CFBundleName = "uBoard";
NSContactsUsageDescription = "undefined";
NSHumanReadableCopyright = "";
# uBoard
A customizable mobile interface to control desktop mouse and keyboard commands
# Setup
Open your mobile browser by scanning the QRCode or enter the URL, then you are able to control your desktop via browser.
## Installation
To run the uBoard server you must have the following installed:
1. nodejs (7.5 or above)
2. npm (5.6.0 or above)
3. bower (1.8.2 or above)
Get required packages
```
$ npm install
```
This will run `bower install` and install client side libraries into `public/vendor`
After, run
```
$ node server.js
```
To host the uBoard server on the desktop.
Next, locate your desktop network IP address. To access the mobile component, open a web browser on a mobile device
and navigate to the IP address of your computer, port 8000
If you are running the desktop executable, you can scan the qr code which will contain the same address
Make sure your mobile device and desktop are running on the same router
## Code structure
The server uses `server.js` and the `socket.io` to change the mouse position and receive keyboard input
The desktop uses `desktop.html` to display the QR code on the desktop window. (NOT FULLY IMPLEMENTED YET)
For the client side, a mobile device will receive `index.html` and its attached `client.js`.
This allows the User to input the keyboard (bottom half of screen) or move the mouse (top half of screen) and emit a WebSocket signal to the server.
## Usage Guide
### Touchpad
The touchpad portion of the interface allows for the following mouse gestures.
* **[Desktop input - Touchpad gesture]**
* Left click - Single one finger tap
* Right click - Single two finger tap
* Double click - Double one finger tap
* Mouse movement - One finger drag
* Scrolling - Two finger drag
* Drag and Drop - Three finger drag
### Keyboard
On tapping buttons on the keyboard, the keys should be typed on your desktop
The following special character keys are current placeholders for utility keys
* @ - Enter
* # - Space
* * - Backspace
The placement and content of the keys can be manipulated by turning on the 'Movable' toggle in the navigation bar.
Once in edit mode, you can drag and drop the placement of keys to change their position.
You can also hold down on a key to update the string content of the key, and save the
current placement and content of the key.
Once saved, anytime you run the application from your current desktop, the mobile
device will load the keyboard layout you set.
## Additional Setup
Additionally your desktop will need to have the appropriate c++ and python libraries
python2 is required to run the robotjs library. Xcode c++ libraries are required to compile robotjs
To install the required c++ Libraries:
On Mac, run
```
xcode-select --install
```
On windows, (TODO)
```
TODO: Fill this in
```
### Building Executable
Clear packages and update to nodejs version 9.x.x
```
$ rm -rf node_modules
$ rm -rf public/vendor
$ nvm install 9
```
Install nwjs and builder
```
$ npm install -g nwjs
$ npm install nwjs-builder-phoenix --save-dev
```
Create executable (dist for all platforms, dist-mac for just macOS)
```
$ npm run dist(-mac)
```
Run app from exe (runs macOS version)
```
$ npm start
```
{
"name": "uBoard",
"description": "",
"homepage": "",
"keywords": [],
"author": "",
"license": "",
"ignore": [
"**/.*",
"node_modules",
"bower_components"
],
"dependencies": {
"bootstrap-material-design": "^0.3.0",
"jquery": "~2.1.3",
"hammerjs": "~2.0.4",
"l20n": "~1.0.2",
"bootstrap": "~3.3.5",
"jquery-qrcode": "*"
}
}
{
"button1": [
"q",
"0",
"0"
],
"button2": [
"w",
"10",
"0"
],
"button3": [
"e",
"20",
"0"
],
"button4": [
"r",
"30",
"0"
],
"button5": [
"t",
"40",
"0"
],
"button6": [
"y",
"50",
"0"
],
"button7": [
"u",
"60",
"0"
],
"button8": [
"W",
"70",
"0"
],
"button9": [
"o",
"80",
"0"
],
"button10": [
"p",
"90",
"0"
],
"button11": [
"a",
"0",
"30"
],
"button12": [
"s",
"10",
"30"
],
"button13": [
"d",
"20",
"30"
],
"button14": [
"f",
"30",
"30"
],
"button15": [
"g",
"40",
"30"
],
"button16": [
"h",
"50",
"30"
],
"button17": [
"j",
"60",
"30"
],
"button18": [
"k",
"70",
"30"
],
"button19": [
"l",
"80",
"30"
],
"button20": [
"z",
"0",
"60"
],
"button21": [
"x",
"10",
"60"
],
"button22": [
"c",
"20",
"60"
],
"button23": [
"v",
"30",
"60"
],
"button24": [
"b",
"40",
"60"
],
"button25": [
"n",
"50",
"60"
],
"button26": [
"m",
"60",
"60"
],
"button27": [
"#",
"70",
"60"
],
"button28": [
"@",
"80",
"60"
],
"button29": [
"*",
"90",
"60"
]
}
\ No newline at end of file
{
"button1": [
"q",
"0",
"0"
],
"button2": [
"w",
"10",
"0"
],
"button3": [
"e",
"20",
"0"
],
"button4": [
"r",
"30",
"0"
],
"button5": [
"t",
"40",
"0"
],
"button6": [
"y",
"50",
"0"
],
"button7": [
"u",
"60",
"0"
],
"button8": [
"i",
"70",
"0"
],
"button9": [
"o",
"80",
"0"
],
"button10": [
"p",
"90",
"0"
],
"button11": [
"a",
"0",
"30"
],
"button12": [
"s",
"10",
"30"
],
"button13": [
"d",
"20",
"30"
],
"button14": [
"f",
"30",
"30"
],
"button15": [
"g",
"40",
"30"
],
"button16": [
"h",
"50",
"30"
],
"button17": [
"j",
"60",
"30"
],
"button18": [
"k",
"70",
"30"
],
"button19": [
"l",
"80",
"30"
],
"button20": [
"z",
"0",
"60"
],
"button21": [
"x",
"10",
"60"
],
"button22": [
"c",
"20",
"60"
],
"button23": [
"v",
"30",
"60"
],
"button24": [
"b",
"40",
"60"
],
"button25": [
"n",
"50",
"60"
],
"button26": [
"m",
"60",
"60"
],
"button0": [
" ",
"70",
"60"
]
}
\ No newline at end of file
<DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>UBoard</title>
<link rel="stylesheet" href="public/vendor/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="public/vendor/bootstrap-material-design/dist/css/ripples.min.css">
<link rel="stylesheet" href="public/vendor/bootstrap-material-design/dist/css/material.min.css">
<link rel="stylesheet" href="public/style/main.css">
</head>
<body fullbleed unresolved class="hidden">
<header class="navbar navbar-inverse navbar-fixed-top shadow-z-2" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle pull-left" data-toggle="collapse" data-target="#pushMenu">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#" data-l10n-id="projectName">UBoard</a>
</div>
<div class="collapse navbar-collapse" id="pushMenu">
<ul class="nav navbar-nav">
<li><a href="#" id="passcode"><i class="mdi-notification-vpn-lock"></i> Pass Code</a></li>
</ul>
</div>
</header>
<section id="content" class="well">
<!-- Add your site or application content here -->
<h3 data-l10n-id="hello">Open Mobile browser with</h3>
<p id="desc" data-l10n-id="info_static"></p>
<div id="qrcode"></div>
</section>
<!-- external libraries -->
<script defer src="public/vendor/jquery/dist/jquery.min.js"></script>
<script defer src="public/vendor/jquery-qrcode/jquery.qrcode.min.js"></script>
<script defer src="public/vendor/bootstrap/dist/js/bootstrap.min.js"></script>
<script defer src="public/vendor/bootstrap-material-design/dist/js/ripples.min.js"></script>
<script defer src="public/vendor/bootstrap-material-design/dist/js/material.min.js"></script>
<script defer src="public/js/main.js"></script>
<script defer src="public/js/desktop.js"></script>
</body>
</html>
0 info it worked if it ends with ok
1 verbose cli [ '/Users/Joshua/.nvm/versions/io.js/v3.3.1/bin/iojs',
1 verbose cli '/Users/Joshua/.nvm/versions/io.js/v3.3.1/bin/npm',
1 verbose cli 'install' ]
2 info using npm@2.14.3
3 info using node@v3.3.1
4 verbose readDependencies loading dependencies from /Users/Joshua/Documents/Michigan Classes/EECS/EECS498/UBoard/project/package.json
5 error install Couldn't read dependencies
6 verbose stack Error: Invalid version: "1.0"
6 verbose stack at Object.module.exports.fixVersionField (/Users/Joshua/.nvm/versions/io.js/v3.3.1/lib/node_modules/npm/node_modules/normalize-package-data/lib/fixer.js:186:13)
6 verbose stack at /Users/Joshua/.nvm/versions/io.js/v3.3.1/lib/node_modules/npm/node_modules/normalize-package-data/lib/normalize.js:32:38
6 verbose stack at Array.forEach (native)
6 verbose stack at normalize (/Users/Joshua/.nvm/versions/io.js/v3.3.1/lib/node_modules/npm/node_modules/normalize-package-data/lib/normalize.js:31:15)
6 verbose stack at final (/Users/Joshua/.nvm/versions/io.js/v3.3.1/lib/node_modules/npm/node_modules/read-package-json/read-json.js:338:5)
6 verbose stack at then (/Users/Joshua/.nvm/versions/io.js/v3.3.1/lib/node_modules/npm/node_modules/read-package-json/read-json.js:113:5)
6 verbose stack at /Users/Joshua/.nvm/versions/io.js/v3.3.1/lib/node_modules/npm/node_modules/read-package-json/read-json.js:300:12
6 verbose stack at FSReqWrap.readFileAfterClose [as oncomplete] (evalmachine.<anonymous>:380:3)
7 verbose cwd /Users/Joshua/Documents/Michigan Classes/EECS/EECS498/UBoard/project
8 error Darwin 16.0.0
9 error argv "/Users/Joshua/.nvm/versions/io.js/v3.3.1/bin/iojs" "/Users/Joshua/.nvm/versions/io.js/v3.3.1/bin/npm" "install"
10 error node v3.3.1
11 error npm v2.14.3
12 error Invalid version: "1.0"
13 error If you need help, you may report this error at:
13 error <https://github.com/npm/npm/issues>
14 verbose exit [ 1, true ]
{"name":"uBoard","version":"1.0.0","main":"desktop.html","window":{"show":true,"toolbar":false,"frame":true,"position":"center","width":480,"height":320,"min_width":480,"min_height":320,"resizable":false,"kiosk":false},"chromium-args":"--child-clean-exit","dependencies":{"express":"^4.13.3","openurl":"^1.1.1","robotjs":"^0.4.7","socket.io":"^1.3.6"}}
\ No newline at end of file
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="public/vendor/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="public/vendor/bootstrap-material-design/dist/css/ripples.min.css">
<link rel="stylesheet" href="public/vendor/bootstrap-material-design/dist/css/material.min.css">
<link rel="stylesheet" href="public/style/main.css">
<link rel="stylesheet" href="public/style/gradient.css">
<title>UBoard</title>
</head>
<body>
<header class="navbar navbar-inverse navbar-fixed-top shadow-z-2" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle pull-left" data-toggle="collapse" data-target="#pushMenu">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#" data-l10n-id="projectName">uBoard</a>
</div>
<div class="collapse navbar-collapse" id="pushMenu">
<ul class="nav navbar-nav">
<!--<li>
<div class="togglebutton">
<label class="navbar-item">
<input type="checkbox" name="checkbox" id="fullscreen-toggle" autocomplete="off"></input>
Touchpad <span class="toggle pull-right"></span>
</label>
</div>
</li>-->
<li>
<div class="togglebutton">
<label class="navbar-item">
<input type="checkbox" name="checkbox" id="move-toggle" autocomplete="off"></input>
Move Buttons <span class="toggle pull-right"></span>
</label>
</div>
</li>
<li class="hidden" id="portrait">
<a href="#">
<i class="mdi-communication-stay-current-portrait"></i> Portrait
</a>
</li>
<li class="hidden" id="landscape">
<a href="#">
<i class="mdi-communication-stay-current-landscape"></i> Landscape
</a>
</li>
<li class="divider"></li>
<li><a href="#" id="passcode"><i class="mdi-notification-vpn-lock"></i> Pass Code</a></li>
<li class="divider"></li>
</ul>
</div>
</header>
<div class="wrapper">
<div class="touchpad" id="touchpad">
</div>
<div class = "keyboard" id="keyboard">
</div>
</div>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Change Input</h4>
</div>
<div id="modal-body">
<p><input type="text" id="inputText" value=""></p>
</div>
<div id="modal-save">
<button type="button" class="btn btn-default" data-dismiss="modal">Save</button>
</div>
<div id="modal-close">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
<script defer src="/public/vendor/jquery/dist/jquery.min.js"></script>
<script defer src="/public/vendor/bootstrap/dist/js/bootstrap.min.js"></script>
<script defer src="/public/vendor/bootstrap-material-design/dist/js/ripples.min.js"></script>
<script defer src="/public/vendor/bootstrap-material-design/dist/js/material.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.2.8/interact.min.js"></script>
<script defer src="/socket.io/socket.io.js"></script>
<script defer src="/public/vendor/hammerjs/hammer.min.js"></script>
<script defer src="/public/style/style.js"></script>
<script defer src="/public/js/client.js"></script>
</body>
</html>
/* jshint node: true */
/* global io, Hammer, $ */
'use strict';
//-----GLOBAL STATE VARIABLES-----//
var socket = io();
var move = false; //Toggles moving functionality
var updateKey; // Modal overlay
var modal = document.getElementById('myModal');// Modal textbox
var inputModal = document.getElementById('inputText');
var keyboardWidth = document.getElementById('keyboard').offsetWidth;// Width pixel of display
var keyboardHeight = document.getElementById('keyboard').offsetHeight;// Height pixel of
//$("#touchpad").hide();
/*
-----------KEYBOARD CONTROLS---------------
The Following Functions Control the KEYBOARD FUNCTIONALITY
*/
//Purpose: Receives information from the server to update the presentation of the keys on the client
socket.on('updateKeys', function(newVals) {
console.log(newVals);
for (var i = 0; i < newVals.x.length; i++){
var ele = $('#button' + (i+1).toString())
ele.text(newVals.k[i])
ele.css({position:'absolute', left:newVals.x[i] + '%', top:(newVals.y[i]) + '%'});
}
});
//Purpose: Emits the key of keyboard upon click
var emitKey = function(str) {
if (move === false){
socket.emit('string', str);
console.log(str);
}
};
//Purpose: Uses interact.js library to enable keys to move around
interact('.draggable').draggable({
snap: {
targets: [
interact.createSnapGrid({ x: .05*keyboardWidth, y: .1*keyboardHeight })
],
range: Infinity
},
inertia: true, // enable inertial throwing
restrict: {
restriction: "parent", // keep the element within the area of it's parent
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},
autoScroll: true, // enable autoScroll
onmove: dragMoveListener, // call this function on every dragmove event
onend: function (event) { // call this function on every dragend event
}
});
function dragMoveListener (event) {
if (move === true){
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
}
//Purpose: Event listener on tapping the keys
interact('.draggable').on('tap', function (event) {
emitKey(event.target.innerText);
}).on('hold', function (event) {
if (move == true){
modal.style.display = "block"; //Allows the modal to be displayed to User
updateKey = event.target
inputModal.value = updateKey.innerText
}
});
//Purpose: Updates button with textbox value
$('#modal-save').click(function() {
var newX = parseInt(updateKey.style.left) + updateKey.getAttribute('data-x')/keyboardWidth*100
var newY = parseInt(updateKey.style.top) + updateKey.getAttribute('data-y')/keyboardHeight*100
newX = Math.min(Math.max(0, newX),100).toString()
newY = Math.min(Math.max(0, newY),100).toString()
console.log(newX, newY)
updateKey.innerText = inputModal.value;
socket.emit('saveKey', {
id: updateKey.id,
val: updateKey.innerText,
x: newX,
y: newY });
});
//Purpose: Closes modal when the user clicks on <span> (x)
$('#modal-close').click(function() {
modal.style.display = "none";
});
//Purpose: Used for resizing and gestures
window.dragMoveListener = dragMoveListener;
/*
-----------MOUSE CONTROLS---------------
The Following Functions Control the Mouse
*/
var touchElem = document.getElementById('touchpad');
var delta = null;
var moving = false;
var control = 'touch';
var passcode = '';
var pos = {x: 0, y: 0, cmd: null, pw: ''};
//Purpose: Wrapper Function to send information from client to server via socket
var emitMouse = function(x, y, cmd) {
pos.x = x;
pos.y = y;
pos.cmd = cmd;
pos.pw = passcode;
socket.emit('mouse', pos);
};
//Purpose: Handles touch movement events from the clients
var handlePan = function(eventName, e) {
if (e.type == eventName + 'start') {
delta = null;
moving = true;
console.log('start ' + eventName);
emitMouse(0, 0, eventName + 'start');
}
if (e.type == eventName + 'end') {
delta = null;
moving = false;
emitMouse(0, 0, eventName + 'end');
}
if (moving && delta != null) {
emitMouse(e.deltaX - delta.x, e.deltaY - delta.y, eventName);
}
delta = {x: e.deltaX, y: e.deltaY};
};
//Purpose: Using Hammer.js library to add different touching functionality
var mc = new Hammer.Manager(touchElem);
mc.add(new Hammer.Pan({event: 'move', threshold: 0, pointers: 1, direction: Hammer.DIRECTION_ALL}));
mc.add(new Hammer.Pan({event: 'scroll', threshold: 0, pointers: 2,direction: Hammer.DIRECTION_ALL}));
mc.add(new Hammer.Pan({event: 'drag', threshold: 0, pointers: 3, direction: Hammer.DIRECTION_ALL}));
//Purpose: Tapping functionality
var singleTap = new Hammer.Tap({event: 'click', pointers: 1});
var doubleTap = new Hammer.Tap({event: 'doubleclick', pointers: 1, taps: 2});
var tripleTap = new Hammer.Tap({event: 'tripleclick', pointers: 1, taps: 3});
mc.add([tripleTap, doubleTap, singleTap]);
tripleTap.recognizeWith([doubleTap, singleTap]);
doubleTap.recognizeWith(singleTap);
doubleTap.requireFailure(tripleTap);
singleTap.requireFailure([tripleTap, doubleTap]);
mc.add(new Hammer.Tap({event: 'rightclick', pointers: 2}));
//Purpose: Using Hammer.js event listeners to trigger functionality by sending data to
mc.on('movestart moveend moveup movedown moveleft moveright', function(e) {
handlePan('move', e);
});
mc.on('scrollstart scrollend scrollup scrolldown scrollleft scrollright',
function(e) {
handlePan('scroll', e);
});
mc.on('dragstart dragend dragup dragdown dragleft dragright', function(e) {
handlePan('drag', e);
});
mc.on('click', function(e) {
console.log('click');
emitMouse(0, 0, 'click');
});
mc.on('rightclick', function(e) {
console.info('rightclick');
emitMouse(0, 0, 'rightclick');
});
mc.on('doubleclick', function(e) {
console.log('doubleclick');
emitMouse(0, 0, 'doubleclick');
});
/*
-----------MENU CONTROLS---------------
The Following Functions Control the Main Menu
*/
document.body.requestFullscreen = document.body.requestFullScreen ||
document.body.webkitRequestFullScreen ||
document.body.mozRequestFullScreen ||
document.body.msRequestFullScreen;
document.cancelFullscreen = document.exitFullscreen ||
document.webkitExitFullscreen ||
document.mozCancelFullScreen ||
document.msExitFullscreen;
//PURPOSE: Toggle movement functionality
$('#fullscreen-toggle').click(function() {
if (this.checked) {
$('.draggable').hide();
$('#keyboard').hide();
$("#touchpad").show();
//document.body.requestFullscreen();
} else {
$('.draggable').show();
$('#keyboard').show();
$("#touchpad").hide();
//document.cancelFullscreen();
}
});
//PURPOSE: Toggle movement functionality
$('#move-toggle').click(function() {
if (this.checked) {
move = true;
} else {
move = false;
}
});
//PURPOSE: If password is set, asks user for password
$('#passcode').click(function() {
passcode = prompt('Enter a passcode');
});
//PURPOSE: About the project
$('#about').click(function() {
if (confirm('UBoard: A mobile mouse for Brad')) {
open('https://github.com/jjlustig/EECS498_uBoard');
}
});
/* jshint node: true */
/* global $ */
'use strict';
$(document).ready(function() {
require('./server.js');
var gui = require('nw.gui');
var os = require('os');
var config = require('./public/js/config.js');
var desc = document.getElementById('desc');
var pw = document.getElementById('passcode');
// show ip address
var ifaces = os.networkInterfaces();
var PORT = 8000;
var url = '';
Object.keys(ifaces).forEach(function(ifname) {
var alias = 0;
ifaces[ifname].forEach(function(iface) {
if ('IPv4' !== iface.family || iface.internal !== false) {
// skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
return;
}
if (alias >= 1) {
// this single interface has multiple ipv4 addresses
// console.log('ifname + ':' + alias, iface.address);
url = 'http://' + iface.address + ':' + PORT;
//desc.innerHTML = url;
} else {
// this interface has only one ipv4 adress
url = 'http://' + iface.address + ':' + PORT;
//desc.innerHTML = url;
}
alias++;
});
});
console.log(url);
// show QRCode
console.log('listening on ' + url);
$('#qrcode').qrcode({width: 128, height: 128, text: url});
// Reference to window and tray
var win = gui.Window.get();
var tray;
// Get the minimize event
win.on('minimize', function() {
// Hide window
this.hide();
});
// Show tray
tray = new gui.Tray({
tooltip: 'UBoard', title: 'UBoard'
});
var menu = new gui.Menu();
menu.append(new gui.MenuItem({
label: 'About UBoard',
click: function() {
if (confirm('UBoard: A mobile mouse for Brad')) {
gui.Shell.openExternal('https://github.com/jjlustig/EECS498_uBoard');
}
}
}));
menu.append(new gui.MenuItem({type: 'separator'}));
menu.append(new gui.MenuItem({
label: 'Show',
click: function() {
win.show();
}
}));
menu.append(new gui.MenuItem({type: 'separator'}));
menu.append(new gui.MenuItem({
label: 'Close',
click: function() {
win.close();
}
}));
tray.menu = menu;
pw.addEventListener('click', function() {
config.passcode = prompt('Enter a passcode');
});
});
/* global $ */
/**
* Main entry point.
*
* the DOM has been localized and the user sees it in their language.
*
* @class Main
*/
(function() {
'use strict';
// document.addEventListener('DocumentLocalized', function() { // l20n ready
document.body.classList.remove('hidden');
$.material.ripples();
// document.addEventListener('deviceready',
// this.onDeviceReady, false); // cordova ready
// });
}());
\ No newline at end of file