initial push...
This commit is contained in:
parent
d82d880a17
commit
938aaca361
|
@ -0,0 +1,41 @@
|
||||||
|
# Dropper
|
||||||
|
Remote Mouse is a flask + pyautogui app to control a PC from your phone or any other device.
|
||||||
|
|
||||||
|
# Notes
|
||||||
|
* Need python 2+
|
||||||
|
* Make sure to change the port in the start script as needed. Have fun!
|
||||||
|
* For Linux you will need to do sudo -i before running the script.
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
*** Change directory to Remote-Mouse/ or rename the folder before doing so.
|
||||||
|
|
||||||
|
``` python3 -m venv venv/ ```
|
||||||
|
|
||||||
|
Linux/Mac
|
||||||
|
``` source bin/activate ```
|
||||||
|
|
||||||
|
Windows
|
||||||
|
``` source bin/Scripts/activate ```
|
||||||
|
|
||||||
|
Linux/Mac
|
||||||
|
``` pip install -r linux-requirements.txt ```
|
||||||
|
|
||||||
|
Windows
|
||||||
|
``` pip install -r windows-requirements.txt ```
|
||||||
|
|
||||||
|
|
||||||
|
``` cd src/ ```
|
||||||
|
|
||||||
|
|
||||||
|
Linux/Mac
|
||||||
|
``` ./linux-start.sh ```
|
||||||
|
|
||||||
|
Windows
|
||||||
|
``` ./windows-start.sh ```
|
||||||
|
|
||||||
|
# Images
|
||||||
|
![1 Interface.... ](images/pic1.png)
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
* Improve mouse translation and speed stepping...
|
||||||
|
* Cleanup code/logic.
|
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
|
@ -0,0 +1,28 @@
|
||||||
|
bcrypt==3.1.7
|
||||||
|
cffi==1.14.0
|
||||||
|
Click==7.0
|
||||||
|
Flask==1.1.1
|
||||||
|
Flask-Bcrypt==0.7.1
|
||||||
|
Flask-Login==0.5.0
|
||||||
|
Flask-SQLAlchemy==2.4.1
|
||||||
|
Flask-WTF==0.14.3
|
||||||
|
gunicorn==19.9.0
|
||||||
|
itsdangerous==1.1.0
|
||||||
|
Jinja2==2.10.3
|
||||||
|
MarkupSafe==1.1.1
|
||||||
|
MouseInfo==0.1.3
|
||||||
|
Pillow==7.1.2
|
||||||
|
pkg-resources==0.0.0
|
||||||
|
PyAutoGUI==0.9.50
|
||||||
|
pycparser==2.20
|
||||||
|
PyGetWindow==0.0.8
|
||||||
|
PyMsgBox==1.0.8
|
||||||
|
pyperclip==1.8.0
|
||||||
|
PyRect==0.1.4
|
||||||
|
PyScreeze==0.1.26
|
||||||
|
python3-xlib==0.15
|
||||||
|
PyTweening==1.0.3
|
||||||
|
six==1.14.0
|
||||||
|
SQLAlchemy==1.3.11
|
||||||
|
Werkzeug==0.16.0
|
||||||
|
WTForms==2.2.1
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Gtk imports
|
||||||
|
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
class MessageHandler:
|
||||||
|
def __init__(self):
|
||||||
|
print("MessageHandler initialized...")
|
||||||
|
|
||||||
|
|
||||||
|
def createMessageJSON(self, type, text):
|
||||||
|
return '{"message": { "type": "' + type + '", "text": "' + text + '" } }'
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Python imports
|
||||||
|
import secrets
|
||||||
|
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
from flask import Flask
|
||||||
|
from flask_bcrypt import Bcrypt
|
||||||
|
from flask_login import current_user, login_user, logout_user, LoginManager
|
||||||
|
|
||||||
|
|
||||||
|
# Apoplication imports
|
||||||
|
|
||||||
|
|
||||||
|
# Configs and 'init'
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///static/db/database.db"
|
||||||
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
app.config['TITLE'] = 'RemoteMouse'
|
||||||
|
|
||||||
|
# For csrf and some other stuff...
|
||||||
|
app.config['SECRET_KEY'] = secrets.token_hex(32)
|
||||||
|
|
||||||
|
|
||||||
|
login_manager = LoginManager(app)
|
||||||
|
bcrypt = Bcrypt(app)
|
||||||
|
|
||||||
|
from core.models import db, User
|
||||||
|
db.init_app(app)
|
||||||
|
|
||||||
|
from core.forms import RegisterForm, LoginForm
|
||||||
|
from core import routes
|
|
@ -0,0 +1,25 @@
|
||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, PasswordField, SubmitField
|
||||||
|
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
|
||||||
|
from core import User
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterForm(FlaskForm):
|
||||||
|
username = StringField('Username', validators=[DataRequired(), Length(min=4, max=24)])
|
||||||
|
email = StringField('Email', validators=[DataRequired(), Email()])
|
||||||
|
password = PasswordField('Password', validators=[DataRequired(), Length(min=8)])
|
||||||
|
confirm_password = PasswordField('Confirm Password',
|
||||||
|
validators=[DataRequired(), EqualTo('password', message="Passwords must match!")])
|
||||||
|
submit = SubmitField("Sign Up")
|
||||||
|
|
||||||
|
def validate_username(self, username):
|
||||||
|
user = User.query.filter_by(username=username.data).first()
|
||||||
|
if user:
|
||||||
|
raise ValidationError("User exists already! Please use a different name!")
|
||||||
|
|
||||||
|
|
||||||
|
class LoginForm(FlaskForm):
|
||||||
|
username = StringField('Username', validators=[DataRequired(), Length(min=4, max=24)])
|
||||||
|
password = PasswordField('Password', validators=[DataRequired(), Length(min=8, max=32)])
|
||||||
|
submit = SubmitField("Login")
|
|
@ -0,0 +1,20 @@
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from core import app, login_manager
|
||||||
|
from flask_login import UserMixin
|
||||||
|
|
||||||
|
|
||||||
|
db = SQLAlchemy(app)
|
||||||
|
|
||||||
|
@login_manager.user_loader
|
||||||
|
def load_user(user_id):
|
||||||
|
return User.query.get(int(user_id))
|
||||||
|
|
||||||
|
|
||||||
|
class User(db.Model, UserMixin):
|
||||||
|
username = db.Column(db.String, unique=True, nullable=False)
|
||||||
|
email = db.Column(db.String, nullable=False)
|
||||||
|
password = db.Column(db.String, nullable=False)
|
||||||
|
id = db.Column(db.Integer, primary_key=True, unique=True, autoincrement=True)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"['{self.username}', '{self.email}', '{self.password}', '{self.id}']"
|
|
@ -0,0 +1,85 @@
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import pyautogui
|
||||||
|
from flask import request, render_template
|
||||||
|
|
||||||
|
# App imports
|
||||||
|
from core import app, db # Get from __init__
|
||||||
|
from core.MessageHandler import MessageHandler # Get simple message processor
|
||||||
|
|
||||||
|
|
||||||
|
msgHandler = MessageHandler()
|
||||||
|
TITLE = app.config['TITLE']
|
||||||
|
pyautogui.FAILSAFE = False # If we hit corner, that's ok
|
||||||
|
pyautogui.MINIMUM_DURATION = 0.5
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET', 'POST'])
|
||||||
|
def home():
|
||||||
|
if request.method == 'GET':
|
||||||
|
return render_template('index.html',
|
||||||
|
title=TITLE)
|
||||||
|
|
||||||
|
return render_template('error.html',
|
||||||
|
title='Error!',
|
||||||
|
message='Must use GET request type...')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/single-click', methods=['GET', 'POST'])
|
||||||
|
def singleClick():
|
||||||
|
pyautogui.click()
|
||||||
|
return ""
|
||||||
|
|
||||||
|
@app.route('/double-click', methods=['GET', 'POST'])
|
||||||
|
def doubleClick():
|
||||||
|
pyautogui.doubleClick()
|
||||||
|
return ""
|
||||||
|
|
||||||
|
@app.route('/get-coords', methods=['GET', 'POST'])
|
||||||
|
def getCoords():
|
||||||
|
x, y = pyautogui.position();
|
||||||
|
return '{"x": "'+ str(x) +'", "y":"' + str(y) + '"}'
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/update-coords', methods=['GET', 'POST'])
|
||||||
|
def updateCoords():
|
||||||
|
if request.method == 'POST':
|
||||||
|
try:
|
||||||
|
x = float( str(request.values['x']).strip() )
|
||||||
|
y = float( str(request.values['y']).strip() )
|
||||||
|
# print("\nX: {} Y: {}".format(str(x), str(y)))
|
||||||
|
pyautogui.moveRel(x, y);
|
||||||
|
except Exception as e:
|
||||||
|
print( repr(e) )
|
||||||
|
return render_template('error.html',
|
||||||
|
title='Error!',
|
||||||
|
message='X or Y is not an integer...')
|
||||||
|
|
||||||
|
return render_template('error.html',
|
||||||
|
title='Error!',
|
||||||
|
message='Must use POST request type...')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/send-key', methods=['GET', 'POST'])
|
||||||
|
def sendKey():
|
||||||
|
pyautogui.doubleClick()
|
||||||
|
if request.method == 'POST':
|
||||||
|
try:
|
||||||
|
text = str(request.values['text']).strip()
|
||||||
|
pyautogui.typewrite(text);
|
||||||
|
|
||||||
|
# print("\nX: {} Y: {}".format(str(x), str(y)))
|
||||||
|
# pyautogui.typewrite('Hello world!\n', interval=secs_between_keys) # useful for entering text, newline is Enter
|
||||||
|
# pyautogui.press(['left', 'left', 'left', 'left']) # Press the left arrow key 4 times.
|
||||||
|
# pyautogui.keyDown('shift') # Press the Shift key down and hold it.
|
||||||
|
# pyautogui.keyUp('shift') # Let go of the Shift key.
|
||||||
|
except Exception as e:
|
||||||
|
print( repr(e) )
|
||||||
|
return render_template('error.html',
|
||||||
|
title='Error!',
|
||||||
|
message='Key is not a valid input...')
|
||||||
|
|
||||||
|
return render_template('error.html',
|
||||||
|
title='Error!',
|
||||||
|
message='Must use POST request type...')
|
|
@ -0,0 +1 @@
|
||||||
|
from . import Routes
|
|
@ -0,0 +1,471 @@
|
||||||
|
/*!
|
||||||
|
* Datepicker for Bootstrap v1.6.4 (https://github.com/eternicode/bootstrap-datepicker)
|
||||||
|
*
|
||||||
|
* Copyright 2012 Stefan Petre
|
||||||
|
* Improvements by Andrew Rowls
|
||||||
|
* Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
*/
|
||||||
|
.datepicker {
|
||||||
|
padding: 4px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
.datepicker-inline {
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
|
.datepicker.datepicker-rtl {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
.datepicker.datepicker-rtl table tr td span {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-bottom: 7px solid #999;
|
||||||
|
border-top: 0;
|
||||||
|
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown:after {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid #fff;
|
||||||
|
border-top: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown.datepicker-orient-left:before {
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown.datepicker-orient-left:after {
|
||||||
|
left: 7px;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown.datepicker-orient-right:before {
|
||||||
|
right: 6px;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown.datepicker-orient-right:after {
|
||||||
|
right: 7px;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown.datepicker-orient-bottom:before {
|
||||||
|
top: -7px;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown.datepicker-orient-bottom:after {
|
||||||
|
top: -6px;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown.datepicker-orient-top:before {
|
||||||
|
bottom: -7px;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-top: 7px solid #999;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown.datepicker-orient-top:after {
|
||||||
|
bottom: -6px;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-top: 6px solid #fff;
|
||||||
|
}
|
||||||
|
.datepicker table {
|
||||||
|
margin: 0;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.datepicker td,
|
||||||
|
.datepicker th {
|
||||||
|
text-align: center;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.table-striped .datepicker table tr td,
|
||||||
|
.table-striped .datepicker table tr th {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.day:hover,
|
||||||
|
.datepicker table tr td.day.focused {
|
||||||
|
background: #eee;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.old,
|
||||||
|
.datepicker table tr td.new {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.disabled,
|
||||||
|
.datepicker table tr td.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: #999;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.highlighted {
|
||||||
|
background: #d9edf7;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today,
|
||||||
|
.datepicker table tr td.today:hover,
|
||||||
|
.datepicker table tr td.today.disabled,
|
||||||
|
.datepicker table tr td.today.disabled:hover {
|
||||||
|
background-color: #fde19a;
|
||||||
|
background-image: -moz-linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||||
|
background-image: -ms-linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
|
||||||
|
background-image: -webkit-linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||||
|
background-image: -o-linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||||
|
background-image: linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
|
||||||
|
border-color: #fdf59a #fdf59a #fbed50;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today:hover,
|
||||||
|
.datepicker table tr td.today:hover:hover,
|
||||||
|
.datepicker table tr td.today.disabled:hover,
|
||||||
|
.datepicker table tr td.today.disabled:hover:hover,
|
||||||
|
.datepicker table tr td.today:active,
|
||||||
|
.datepicker table tr td.today:hover:active,
|
||||||
|
.datepicker table tr td.today.disabled:active,
|
||||||
|
.datepicker table tr td.today.disabled:hover:active,
|
||||||
|
.datepicker table tr td.today.active,
|
||||||
|
.datepicker table tr td.today:hover.active,
|
||||||
|
.datepicker table tr td.today.disabled.active,
|
||||||
|
.datepicker table tr td.today.disabled:hover.active,
|
||||||
|
.datepicker table tr td.today.disabled,
|
||||||
|
.datepicker table tr td.today:hover.disabled,
|
||||||
|
.datepicker table tr td.today.disabled.disabled,
|
||||||
|
.datepicker table tr td.today.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td.today[disabled],
|
||||||
|
.datepicker table tr td.today:hover[disabled],
|
||||||
|
.datepicker table tr td.today.disabled[disabled],
|
||||||
|
.datepicker table tr td.today.disabled:hover[disabled] {
|
||||||
|
background-color: #fdf59a;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today:active,
|
||||||
|
.datepicker table tr td.today:hover:active,
|
||||||
|
.datepicker table tr td.today.disabled:active,
|
||||||
|
.datepicker table tr td.today.disabled:hover:active,
|
||||||
|
.datepicker table tr td.today.active,
|
||||||
|
.datepicker table tr td.today:hover.active,
|
||||||
|
.datepicker table tr td.today.disabled.active,
|
||||||
|
.datepicker table tr td.today.disabled:hover.active {
|
||||||
|
background-color: #fbf069 \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today:hover:hover {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today.active:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.range,
|
||||||
|
.datepicker table tr td.range:hover,
|
||||||
|
.datepicker table tr td.range.disabled,
|
||||||
|
.datepicker table tr td.range.disabled:hover {
|
||||||
|
background: #eee;
|
||||||
|
-webkit-border-radius: 0;
|
||||||
|
-moz-border-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.range.today,
|
||||||
|
.datepicker table tr td.range.today:hover,
|
||||||
|
.datepicker table tr td.range.today.disabled,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover {
|
||||||
|
background-color: #f3d17a;
|
||||||
|
background-image: -moz-linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||||
|
background-image: -ms-linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
|
||||||
|
background-image: -webkit-linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||||
|
background-image: -o-linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||||
|
background-image: linear-gradient(to bottom, #f3c17a, #f3e97a);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
|
||||||
|
border-color: #f3e97a #f3e97a #edde34;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
-webkit-border-radius: 0;
|
||||||
|
-moz-border-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.range.today:hover,
|
||||||
|
.datepicker table tr td.range.today:hover:hover,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover:hover,
|
||||||
|
.datepicker table tr td.range.today:active,
|
||||||
|
.datepicker table tr td.range.today:hover:active,
|
||||||
|
.datepicker table tr td.range.today.disabled:active,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover:active,
|
||||||
|
.datepicker table tr td.range.today.active,
|
||||||
|
.datepicker table tr td.range.today:hover.active,
|
||||||
|
.datepicker table tr td.range.today.disabled.active,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover.active,
|
||||||
|
.datepicker table tr td.range.today.disabled,
|
||||||
|
.datepicker table tr td.range.today:hover.disabled,
|
||||||
|
.datepicker table tr td.range.today.disabled.disabled,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td.range.today[disabled],
|
||||||
|
.datepicker table tr td.range.today:hover[disabled],
|
||||||
|
.datepicker table tr td.range.today.disabled[disabled],
|
||||||
|
.datepicker table tr td.range.today.disabled:hover[disabled] {
|
||||||
|
background-color: #f3e97a;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.range.today:active,
|
||||||
|
.datepicker table tr td.range.today:hover:active,
|
||||||
|
.datepicker table tr td.range.today.disabled:active,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover:active,
|
||||||
|
.datepicker table tr td.range.today.active,
|
||||||
|
.datepicker table tr td.range.today:hover.active,
|
||||||
|
.datepicker table tr td.range.today.disabled.active,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover.active {
|
||||||
|
background-color: #efe24b \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.selected,
|
||||||
|
.datepicker table tr td.selected:hover,
|
||||||
|
.datepicker table tr td.selected.disabled,
|
||||||
|
.datepicker table tr td.selected.disabled:hover {
|
||||||
|
background-color: #9e9e9e;
|
||||||
|
background-image: -moz-linear-gradient(to bottom, #b3b3b3, #808080);
|
||||||
|
background-image: -ms-linear-gradient(to bottom, #b3b3b3, #808080);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
|
||||||
|
background-image: -webkit-linear-gradient(to bottom, #b3b3b3, #808080);
|
||||||
|
background-image: -o-linear-gradient(to bottom, #b3b3b3, #808080);
|
||||||
|
background-image: linear-gradient(to bottom, #b3b3b3, #808080);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
|
||||||
|
border-color: #808080 #808080 #595959;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.datepicker table tr td.selected:hover,
|
||||||
|
.datepicker table tr td.selected:hover:hover,
|
||||||
|
.datepicker table tr td.selected.disabled:hover,
|
||||||
|
.datepicker table tr td.selected.disabled:hover:hover,
|
||||||
|
.datepicker table tr td.selected:active,
|
||||||
|
.datepicker table tr td.selected:hover:active,
|
||||||
|
.datepicker table tr td.selected.disabled:active,
|
||||||
|
.datepicker table tr td.selected.disabled:hover:active,
|
||||||
|
.datepicker table tr td.selected.active,
|
||||||
|
.datepicker table tr td.selected:hover.active,
|
||||||
|
.datepicker table tr td.selected.disabled.active,
|
||||||
|
.datepicker table tr td.selected.disabled:hover.active,
|
||||||
|
.datepicker table tr td.selected.disabled,
|
||||||
|
.datepicker table tr td.selected:hover.disabled,
|
||||||
|
.datepicker table tr td.selected.disabled.disabled,
|
||||||
|
.datepicker table tr td.selected.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td.selected[disabled],
|
||||||
|
.datepicker table tr td.selected:hover[disabled],
|
||||||
|
.datepicker table tr td.selected.disabled[disabled],
|
||||||
|
.datepicker table tr td.selected.disabled:hover[disabled] {
|
||||||
|
background-color: #808080;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.selected:active,
|
||||||
|
.datepicker table tr td.selected:hover:active,
|
||||||
|
.datepicker table tr td.selected.disabled:active,
|
||||||
|
.datepicker table tr td.selected.disabled:hover:active,
|
||||||
|
.datepicker table tr td.selected.active,
|
||||||
|
.datepicker table tr td.selected:hover.active,
|
||||||
|
.datepicker table tr td.selected.disabled.active,
|
||||||
|
.datepicker table tr td.selected.disabled:hover.active {
|
||||||
|
background-color: #666666 \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.active,
|
||||||
|
.datepicker table tr td.active:hover,
|
||||||
|
.datepicker table tr td.active.disabled,
|
||||||
|
.datepicker table tr td.active.disabled:hover {
|
||||||
|
background-color: #006dcc;
|
||||||
|
background-image: -moz-linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-image: -ms-linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0044cc));
|
||||||
|
background-image: -webkit-linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-image: -o-linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-image: linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#08c', endColorstr='#0044cc', GradientType=0);
|
||||||
|
border-color: #0044cc #0044cc #002a80;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.datepicker table tr td.active:hover,
|
||||||
|
.datepicker table tr td.active:hover:hover,
|
||||||
|
.datepicker table tr td.active.disabled:hover,
|
||||||
|
.datepicker table tr td.active.disabled:hover:hover,
|
||||||
|
.datepicker table tr td.active:active,
|
||||||
|
.datepicker table tr td.active:hover:active,
|
||||||
|
.datepicker table tr td.active.disabled:active,
|
||||||
|
.datepicker table tr td.active.disabled:hover:active,
|
||||||
|
.datepicker table tr td.active.active,
|
||||||
|
.datepicker table tr td.active:hover.active,
|
||||||
|
.datepicker table tr td.active.disabled.active,
|
||||||
|
.datepicker table tr td.active.disabled:hover.active,
|
||||||
|
.datepicker table tr td.active.disabled,
|
||||||
|
.datepicker table tr td.active:hover.disabled,
|
||||||
|
.datepicker table tr td.active.disabled.disabled,
|
||||||
|
.datepicker table tr td.active.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td.active[disabled],
|
||||||
|
.datepicker table tr td.active:hover[disabled],
|
||||||
|
.datepicker table tr td.active.disabled[disabled],
|
||||||
|
.datepicker table tr td.active.disabled:hover[disabled] {
|
||||||
|
background-color: #0044cc;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.active:active,
|
||||||
|
.datepicker table tr td.active:hover:active,
|
||||||
|
.datepicker table tr td.active.disabled:active,
|
||||||
|
.datepicker table tr td.active.disabled:hover:active,
|
||||||
|
.datepicker table tr td.active.active,
|
||||||
|
.datepicker table tr td.active:hover.active,
|
||||||
|
.datepicker table tr td.active.disabled.active,
|
||||||
|
.datepicker table tr td.active.disabled:hover.active {
|
||||||
|
background-color: #003399 \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span {
|
||||||
|
display: block;
|
||||||
|
width: 23%;
|
||||||
|
height: 54px;
|
||||||
|
line-height: 54px;
|
||||||
|
float: left;
|
||||||
|
margin: 1%;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span:hover,
|
||||||
|
.datepicker table tr td span.focused {
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.disabled,
|
||||||
|
.datepicker table tr td span.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: #999;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.active,
|
||||||
|
.datepicker table tr td span.active:hover,
|
||||||
|
.datepicker table tr td span.active.disabled,
|
||||||
|
.datepicker table tr td span.active.disabled:hover {
|
||||||
|
background-color: #006dcc;
|
||||||
|
background-image: -moz-linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-image: -ms-linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0044cc));
|
||||||
|
background-image: -webkit-linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-image: -o-linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-image: linear-gradient(to bottom, #08c, #0044cc);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#08c', endColorstr='#0044cc', GradientType=0);
|
||||||
|
border-color: #0044cc #0044cc #002a80;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.active:hover,
|
||||||
|
.datepicker table tr td span.active:hover:hover,
|
||||||
|
.datepicker table tr td span.active.disabled:hover,
|
||||||
|
.datepicker table tr td span.active.disabled:hover:hover,
|
||||||
|
.datepicker table tr td span.active:active,
|
||||||
|
.datepicker table tr td span.active:hover:active,
|
||||||
|
.datepicker table tr td span.active.disabled:active,
|
||||||
|
.datepicker table tr td span.active.disabled:hover:active,
|
||||||
|
.datepicker table tr td span.active.active,
|
||||||
|
.datepicker table tr td span.active:hover.active,
|
||||||
|
.datepicker table tr td span.active.disabled.active,
|
||||||
|
.datepicker table tr td span.active.disabled:hover.active,
|
||||||
|
.datepicker table tr td span.active.disabled,
|
||||||
|
.datepicker table tr td span.active:hover.disabled,
|
||||||
|
.datepicker table tr td span.active.disabled.disabled,
|
||||||
|
.datepicker table tr td span.active.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td span.active[disabled],
|
||||||
|
.datepicker table tr td span.active:hover[disabled],
|
||||||
|
.datepicker table tr td span.active.disabled[disabled],
|
||||||
|
.datepicker table tr td span.active.disabled:hover[disabled] {
|
||||||
|
background-color: #0044cc;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.active:active,
|
||||||
|
.datepicker table tr td span.active:hover:active,
|
||||||
|
.datepicker table tr td span.active.disabled:active,
|
||||||
|
.datepicker table tr td span.active.disabled:hover:active,
|
||||||
|
.datepicker table tr td span.active.active,
|
||||||
|
.datepicker table tr td span.active:hover.active,
|
||||||
|
.datepicker table tr td span.active.disabled.active,
|
||||||
|
.datepicker table tr td span.active.disabled:hover.active {
|
||||||
|
background-color: #003399 \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.old,
|
||||||
|
.datepicker table tr td span.new {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.datepicker .datepicker-switch {
|
||||||
|
width: 145px;
|
||||||
|
}
|
||||||
|
.datepicker .datepicker-switch,
|
||||||
|
.datepicker .prev,
|
||||||
|
.datepicker .next,
|
||||||
|
.datepicker tfoot tr th {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.datepicker .datepicker-switch:hover,
|
||||||
|
.datepicker .prev:hover,
|
||||||
|
.datepicker .next:hover,
|
||||||
|
.datepicker tfoot tr th:hover {
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
.datepicker .cw {
|
||||||
|
font-size: 10px;
|
||||||
|
width: 12px;
|
||||||
|
padding: 0 2px 0 5px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.input-append.date .add-on,
|
||||||
|
.input-prepend.date .add-on {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.input-append.date .add-on i,
|
||||||
|
.input-prepend.date .add-on i {
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
.input-daterange input {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.input-daterange input:first-child {
|
||||||
|
-webkit-border-radius: 3px 0 0 3px;
|
||||||
|
-moz-border-radius: 3px 0 0 3px;
|
||||||
|
border-radius: 3px 0 0 3px;
|
||||||
|
}
|
||||||
|
.input-daterange input:last-child {
|
||||||
|
-webkit-border-radius: 0 3px 3px 0;
|
||||||
|
-moz-border-radius: 0 3px 3px 0;
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
}
|
||||||
|
.input-daterange .add-on {
|
||||||
|
display: inline-block;
|
||||||
|
width: auto;
|
||||||
|
min-width: 16px;
|
||||||
|
height: 18px;
|
||||||
|
padding: 4px 5px;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 0 1px 0 #fff;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-color: #eee;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
margin-left: -5px;
|
||||||
|
margin-right: -5px;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=bootstrap-datepicker.css.map */
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,77 @@
|
||||||
|
/* Elms */
|
||||||
|
ul, li {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
overflow: hidden; /* Used to prevent touch scroll down reloading page. Ref: https://stackoverflow.com/questions/29008194/disabling-androids-chrome-pull-down-to-refresh-feature */
|
||||||
|
-webkit-touch-callout: none; /* iOS Safari */
|
||||||
|
-webkit-user-select: none; /* Safari */
|
||||||
|
-khtml-user-select: none; /* Konqueror HTML */
|
||||||
|
-moz-user-select: none; /* Old versions of Firefox */
|
||||||
|
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||||
|
user-select: none; /* Non-prefixed version, currently
|
||||||
|
supported by Chrome, Opera and Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 75% !important;
|
||||||
|
margin: 0 auto !important;
|
||||||
|
font-size: 200% !important;
|
||||||
|
background-color: #00000000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* IDs */
|
||||||
|
#bg {
|
||||||
|
position: fixed;
|
||||||
|
top: 0%;
|
||||||
|
left: 0%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bg img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 65em;
|
||||||
|
background-color: rgba(56, 56, 56, 0.67);
|
||||||
|
}
|
||||||
|
|
||||||
|
#singleClickBtn, #doubleClickBtn {
|
||||||
|
background-color: #62c462;
|
||||||
|
border-style: dashed;
|
||||||
|
border-width: 2px;
|
||||||
|
overflow: auto;
|
||||||
|
height: 8em;
|
||||||
|
font-size: 200%;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#singleClickBtn:hover,
|
||||||
|
#doubleClickBtn:hover,
|
||||||
|
#singleClickBtn:active,
|
||||||
|
#doubleClickBtn:active {
|
||||||
|
background-color: rgba(0, 232, 255, 0.5);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sendKeysBtn { width: 8em; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Classes */
|
||||||
|
/* Other message text colors */
|
||||||
|
.errorTxt { color: rgb(170, 18, 18); }
|
||||||
|
.warningTxt { color: rgb(255, 168, 0); }
|
||||||
|
.successTxt { color: rgb(136, 204, 39); }
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
After Width: | Height: | Size: 504 KiB |
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
|
@ -0,0 +1,22 @@
|
||||||
|
const doAjax = (actionPath, data, action) => {
|
||||||
|
let xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.open("POST", actionPath, true);
|
||||||
|
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
|
// Force return to be JSON NOTE: Use application/xml to force XML
|
||||||
|
xhttp.overrideMimeType('application/json');
|
||||||
|
xhttp.send(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatURL = (basePath) => {
|
||||||
|
url = window.location.href;
|
||||||
|
if ( url.endsWith('/') )
|
||||||
|
return url + basePath;
|
||||||
|
else
|
||||||
|
return url + '/' + basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchData = async (url) => {
|
||||||
|
let response = null;
|
||||||
|
response = await fetch(url);
|
||||||
|
return await response.json();
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,143 @@
|
||||||
|
// When true, moving the mouse updates coords
|
||||||
|
const canvas = document.getElementById("canvas");
|
||||||
|
let isDragging = false;
|
||||||
|
let runUpdate = false;
|
||||||
|
let xLast = 0;
|
||||||
|
let yLast = 0;
|
||||||
|
let mod = 2;
|
||||||
|
let px = 0;
|
||||||
|
let py = 0;
|
||||||
|
let x1 = 0;
|
||||||
|
let y1 = 0;
|
||||||
|
let x2 = 0;
|
||||||
|
let y2 = 0;
|
||||||
|
let m = undefined; // slope value
|
||||||
|
|
||||||
|
|
||||||
|
canvas.addEventListener('touchstart', e => { onPress(e); });
|
||||||
|
canvas.addEventListener('mousedown', e => { onPress(e); });
|
||||||
|
canvas.addEventListener('touchmove', e => { onMoveing(e); });
|
||||||
|
canvas.addEventListener('mousemove', e => { onMoveing(e); });
|
||||||
|
canvas.addEventListener('touchend', e => { onRelease(e); });
|
||||||
|
canvas.addEventListener('mouseup', e => { onRelease(e); });
|
||||||
|
|
||||||
|
|
||||||
|
// Run update when true every 100 ms
|
||||||
|
setInterval(function () {
|
||||||
|
if (runUpdate) {
|
||||||
|
doAjax("/update-coords", "x=" + px + "&y=" + py, "move");
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// Update mod
|
||||||
|
setInterval(function () {
|
||||||
|
if (runUpdate) {
|
||||||
|
mod += 1;
|
||||||
|
}
|
||||||
|
}, 250);
|
||||||
|
|
||||||
|
|
||||||
|
const onPress = (e) => {
|
||||||
|
isDragging = true;
|
||||||
|
runUpdate = true;
|
||||||
|
xLast = e.offsetX;
|
||||||
|
yLast = e.offsetY;
|
||||||
|
updateText(xLast, yLast);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const onMoveing = (e) => {
|
||||||
|
if (isDragging === true) {
|
||||||
|
x1 = xLast;
|
||||||
|
y1 = yLast;
|
||||||
|
|
||||||
|
if (e.type === 'mousemove') {
|
||||||
|
x2 = e.offsetX;
|
||||||
|
y2 = e.offsetY;
|
||||||
|
xLast = e.offsetX;
|
||||||
|
yLast = e.offsetY;
|
||||||
|
} else if (e.type === 'touchmove') {
|
||||||
|
x2 = parseInt(e.touches[0].clientX, 10);
|
||||||
|
y2 = parseInt(e.touches[0].clientY, 10);
|
||||||
|
xLast = parseInt(e.touches[0].clientX, 10);
|
||||||
|
yLast = parseInt(e.touches[0].clientY, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the delta of the points
|
||||||
|
if (x2 > x1) {
|
||||||
|
px = mod // Is growing
|
||||||
|
} else {
|
||||||
|
px = -mod // Is shrinking
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y2 > y1) {
|
||||||
|
py = mod // Is growing
|
||||||
|
} else {
|
||||||
|
py = -mod // Is shrinking
|
||||||
|
}
|
||||||
|
|
||||||
|
m = (y2-y1)/(x2-x1)
|
||||||
|
if (m === undefined) {
|
||||||
|
py = 0;
|
||||||
|
} else if (!isFinite(m)) {
|
||||||
|
px = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (m > 0.05 && m <= 1) && (m > -0.05 && m >= -1) ) {
|
||||||
|
py = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateText(px, py);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const onRelease = (e) => {
|
||||||
|
if (isDragging === true) {
|
||||||
|
isDragging = false;
|
||||||
|
runUpdate = false;
|
||||||
|
mod = 3;
|
||||||
|
xLast = 0;
|
||||||
|
yLast = 0;
|
||||||
|
px = 0;
|
||||||
|
py = 0;
|
||||||
|
updateText(px, py);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const updateText = (x, y) => {
|
||||||
|
const coordsTxt = "X coords: " + x + ", Y coords: " + y;
|
||||||
|
document.getElementById("cordsText").innerText = coordsTxt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Click events
|
||||||
|
document.getElementById("singleClickBtn").addEventListener('mouseup', e => { onSingleClick(e); });
|
||||||
|
document.getElementById("singleClickBtn").addEventListener('touchend', e => { onSingleClick(e); });
|
||||||
|
document.getElementById("doubleClickBtn").addEventListener('mouseup', e => { onDoubleClick(e); });
|
||||||
|
document.getElementById("doubleClickBtn").addEventListener('touchend', e => { onDoubleClick(e); });
|
||||||
|
|
||||||
|
const onSingleClick = (e) => {
|
||||||
|
doAjax("/single-click", "ref=null", "singleClick");
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDoubleClick = (e) => {
|
||||||
|
doAjax("/double-click", "ref=null", "doubleClick");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Key input events
|
||||||
|
// document.getElementById("sendKeysField").addEventListener('input', e => { onSendKeys(e); });
|
||||||
|
// document.getElementById("sendKeysField").addEventListener('change', e => { onSendKeys(e); });
|
||||||
|
document.getElementById("sendKeysBtn").addEventListener('mouseup', e => { onSendKeys(e); });
|
||||||
|
document.getElementById("sendKeysBtn").addEventListener('touchend', e => { onSendKeys(e); });
|
||||||
|
|
||||||
|
const onSendKeys = (e) => {
|
||||||
|
let target = document.getElementById("sendKeysField");
|
||||||
|
const text = target.value;
|
||||||
|
doAjax("/send-key", "text=" + text, "sendKeys");
|
||||||
|
target.value = "";
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col justify-content-center text-center">
|
||||||
|
<h1 class="errorTxt">{{title}}</h1>
|
||||||
|
<p>{{message}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<!-- Created scripts -->
|
||||||
|
{% endblock scripts %}
|
|
@ -0,0 +1,41 @@
|
||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block body_header_additional %}
|
||||||
|
{% endblock body_header_additional %}
|
||||||
|
|
||||||
|
{% block body_content %}
|
||||||
|
<div class="container-auto">
|
||||||
|
<div class="row">
|
||||||
|
<div id="singleClickBtn" class="col justify-content-center text-center">
|
||||||
|
Single-Click
|
||||||
|
</div>
|
||||||
|
<div id="doubleClickBtn" class="col justify-content-center text-center">
|
||||||
|
Double-Click
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br/><br/>
|
||||||
|
<div class="row">
|
||||||
|
<input id="sendKeysField" type="text" value="" class="form-control" placeholder="Send keys...">
|
||||||
|
<button id="sendKeysBtn" class="btn btn-success">Send</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="canvas" class="container-auto">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col justify-content-center text-center">
|
||||||
|
<div id="cordsText" style="font-size: 280%;">
|
||||||
|
X coords: 0, Y coords: 0
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock body_content %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block body_footer_additional %}
|
||||||
|
{% endblock body_footer_additional %}
|
||||||
|
|
||||||
|
{% block body_scripts_additional %}
|
||||||
|
<script src="{{url_for('static', filename='js/ajax.js')}}"></script>
|
||||||
|
<script src="{{url_for('static', filename='js/events.js')}}"></script>
|
||||||
|
<script src="{{url_for('static', filename='js/draging.js')}}"></script>
|
||||||
|
{% endblock body_scripts_additional %}
|
|
@ -0,0 +1,84 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
{% if title %}
|
||||||
|
<title>{{title}}</title>
|
||||||
|
{% else %}
|
||||||
|
<title>App</title>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block header_css %}
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.png') }}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap/bootstrap.min.css')}}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap/bootstrap-datepicker.css')}}">
|
||||||
|
|
||||||
|
<!-- Font Awesome CSS Notes -->
|
||||||
|
<!-- <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous"> -->
|
||||||
|
<!-- https://use.fontawesome.com/releases/v5.7.0/webfonts/fa-regular-400.woff2 -->
|
||||||
|
<!-- https://use.fontawesome.com/releases/v5.7.0/webfonts/ -->
|
||||||
|
|
||||||
|
<!-- Site Font Awesome CSS -->
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/font-awesome/font-awesome-all-v5.7.css')}}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/font-awesome/font-awesome-min-v4.7.0.css')}}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/font-awesome/font-awesome-woff2.css')}}">
|
||||||
|
|
||||||
|
<!-- Site CSS -->
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css')}}">
|
||||||
|
{% block header_css_additional %}
|
||||||
|
{% endblock header_css_additional %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block header_scripts %}
|
||||||
|
{% block header_scripts_additional %}
|
||||||
|
{% endblock header_scripts_additional %}
|
||||||
|
{% endblock %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- <img id="bg" src="{{ url_for('static', filename='imgs/backgrounds/background.jpg')}}" alt="{{title}} Background Logo" /> -->
|
||||||
|
|
||||||
|
{% block body_header %}
|
||||||
|
{% block body_header_additional %}
|
||||||
|
{% endblock body_header_additional%}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
<!-- System flashed messages! -->
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% if messages %}
|
||||||
|
<div class=flashes>
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<li class="alert alert-{{ category }}">{{ message }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
{% block body_content %}
|
||||||
|
{% block body_content_additional %}
|
||||||
|
{% endblock body_content_additional%}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block body_footer %}
|
||||||
|
{% block body_footer_additional %}
|
||||||
|
{% endblock body_footer_additional%}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block body_scripts %}
|
||||||
|
<!-- For Bootstrap in this exact order... -->
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap/jquery-3.3.1.slim.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap/popper.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap/bootstrap.min.js')}}"></script>
|
||||||
|
|
||||||
|
<!-- For DatePicker -->
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap/moment.min.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap/bootstrap-datepicker.min.js')}}"></script>
|
||||||
|
{% block body_scripts_additional %}
|
||||||
|
{% endblock body_scripts_additional%}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# set -o xtrace ## To debug scripts
|
||||||
|
# set -o errexit ## To exit on error
|
||||||
|
# set -o errunset ## To exit if a variable is referenced but not set
|
||||||
|
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
source "../venv/bin/activate"
|
||||||
|
# Note can replace 127.0.0.1 with 0.0.0.0 to make it 'network/internet' accessable...
|
||||||
|
gunicorn wsgi:app -b 127.0.0.1:8080 # <module>:<app> IE <file>:<flask app variable>
|
||||||
|
}
|
||||||
|
main $@;
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# set -o xtrace ## To debug scripts
|
||||||
|
# set -o errexit ## To exit on error
|
||||||
|
# set -o errunset ## To exit if a variable is referenced but not set
|
||||||
|
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
source "../venv/Scripts/activate"
|
||||||
|
# Note can replace 127.0.0.1 with 0.0.0.0 to make it 'network/internet' accessable...
|
||||||
|
waitress-serve --listen=127.0.0.1:8080 wsgi:app # <module>:<app> IE <file>:<flask app variable>
|
||||||
|
}
|
||||||
|
main $@;
|
|
@ -0,0 +1,4 @@
|
||||||
|
from core import app
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True)
|
|
@ -0,0 +1,28 @@
|
||||||
|
bcrypt==3.1.7
|
||||||
|
cffi==1.14.0
|
||||||
|
Click==7.0
|
||||||
|
Flask==1.1.1
|
||||||
|
Flask-Bcrypt==0.7.1
|
||||||
|
Flask-Login==0.5.0
|
||||||
|
Flask-SQLAlchemy==2.4.1
|
||||||
|
Flask-WTF==0.14.3
|
||||||
|
waitress==1.4.3
|
||||||
|
itsdangerous==1.1.0
|
||||||
|
Jinja2==2.10.3
|
||||||
|
MarkupSafe==1.1.1
|
||||||
|
MouseInfo==0.1.3
|
||||||
|
Pillow==7.1.2
|
||||||
|
pkg-resources==0.0.0
|
||||||
|
PyAutoGUI==0.9.50
|
||||||
|
pycparser==2.20
|
||||||
|
PyGetWindow==0.0.8
|
||||||
|
PyMsgBox==1.0.8
|
||||||
|
pyperclip==1.8.0
|
||||||
|
PyRect==0.1.4
|
||||||
|
PyScreeze==0.1.26
|
||||||
|
python3-xlib==0.15
|
||||||
|
PyTweening==1.0.3
|
||||||
|
six==1.14.0
|
||||||
|
SQLAlchemy==1.3.11
|
||||||
|
Werkzeug==0.16.0
|
||||||
|
WTForms==2.2.1
|
Loading…
Reference in New Issue