├── .gitignore ├── LICENSE ├── README.md ├── app.py ├── bus.py ├── ocw.sh └── web ├── css ├── fa.solid.css ├── ocw.main.css ├── reset.css └── vue.slider.css ├── fonts ├── fa-solid-900.eot ├── fa-solid-900.svg ├── fa-solid-900.ttf ├── fa-solid-900.woff └── fa-solid-900.woff2 ├── img ├── api.gif ├── favicon.png └── web.gif ├── js ├── jquery.min.js ├── nipple.min.js ├── ocw.api.js ├── ocw.log.js ├── ocw.main.js ├── vue.min.js └── vue.slider.min.js └── main.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 leukipp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenCatWeb (v0.3) 2 | > Web API for Petoi OpenCat Robotics 3 | 4 | This is an extension for Petoi OpenCat robotic kittens. 5 | It offers a local running Web API for `GET` requests with `JSON` responses. 6 | 7 | There is also a simple web application with the following features included. 8 | - Control individual servo positions 9 | - Control walking mode and head with virtual joysticks 10 | - Send commands by predefined buttons (like on IR remote control) 11 | - Send individual commands by text (like on serial terminal) 12 | 13 | ## Requirements 14 | ### Hardware 15 | - Working and calibrated OpenCat robot (like Nybble) with NyBoard v0_x 16 | - Working Raspberry Pi mounted on top of NyBoard 17 | 18 | There are no other hardware or software changes necessary on NyBoard side. 19 | The following steps are for Raspberry Pi with Raspbian, but the code will also work on any other hardware with serial access to NyBoard. 20 | 21 | ### Software 22 | - Working SSH or VNC access on Raspberry Pi 23 | - Working NyBoard serial communication on Raspberry Pi 24 | - Follow the chapter **"Raspberry Pi serial port as interface"** in [OpenCat documentation](https://github.com/PetoiCamp/OpenCat/blob/master/Resources/AssemblingInstructions.pdf) 25 | 26 | 27 | ## Installation 28 | ### Dependencies 29 | OpenCatWeb uses `Flask` as Python Web Server Gateway Interface (WSGI). 30 | 31 | pip install Flask 32 | 33 | That's it, now we need the source code of OpenCatWeb. 34 | 35 | ### Source code 36 | Create the folder `/home/pi/Projects`. 37 | 38 | cd ~ 39 | mkdir Projects 40 | cd Projects 41 | 42 | Use `git` or download the source code as zip. 43 | 44 | sudo apt-get install git 45 | git clone https://github.com/leukipp/OpenCatWeb.git 46 | 47 | You should now have the folder `/home/pi/Projects/OpenCatWeb`. 48 | 49 | 50 | ## Running 51 | ### First start 52 | Start the webserver at port `8080`. 53 | 54 | cd OpenCatWeb 55 | chmod +x bus.py app.py 56 | ./app.py 57 | 58 | Open the web browser on another device in the same network and enter `http://:8080/`. 59 | 60 | You should see the welcome screen (more in **Usage**) 61 | >- /web/ 62 | >- /api/ 63 | 64 | _You can modify the webserver settings at `HOST = '0.0.0.0'` and `PORT = 8080` in `app.py` to your requirements._ 65 | _Don't change and leave `DEBUG = true`, your server won't boot up with auto start._ 66 | 67 | ### Auto start on boot 68 | _You can change the folder structure for auto start at `DAEMON=/home/pi/Projects/OpenCatWeb/app.py` in `ocw.sh` to your requirements._ 69 | 70 | chmod +x ocw.sh 71 | sudo cp ocw.sh /etc/init.d/ 72 | sudo update-rc.d ocw.sh defaults 73 | 74 | Reboot and check if everything is running on startup. 75 | 76 | 77 | ## Usage 78 | The documentation of available commands is on the webserver and 79 | in the chapter **"Arduino IDE as interface"** in [OpenCat documentation](https://github.com/PetoiCamp/OpenCat/blob/master/Resources/AssemblingInstructions.pdf). 80 | 81 | ### API 82 | ![Screenshot](https://github.com/leukipp/OpenCatWeb/blob/master/web/img/api.gif?raw=true) 83 | 84 | I have decided to use `GET` for several reasons, most of them because of simplicity. 85 | You don't have to use any special software to control your robot. 86 | A simple browser bookmark is enough to do anything! 87 | 88 | >You can navigate through all API path's until you reach the end. 89 | >- /web/ 90 | >- /api/ 91 | > - command/\ 92 | > - communicate/ 93 | > - u/\/\ 94 | > - b/\/\ 95 | > - move/ 96 | > - m/\/\ 97 | > - i/\/\/\/\/... 98 | > - l/\/.../\ 99 | > - stop/ 100 | > - d 101 | > - p 102 | > - r 103 | > - status/ 104 | > - j 105 | 106 | For every `GET` request on the bottom of the list you will get a `application/json` response. For all others you will get a `text/html` response. 107 | For status commands the API response contains the parsed text from the serial output. 108 | 109 | Commands for calibration (c, s, a) are not implemented for safety reasons. 110 | 111 | ### WEB 112 | ![Screenshot](https://github.com/leukipp/OpenCatWeb/blob/master/web/img/web.gif?raw=true) 113 | 114 | On the first page you are able to send predefined commands by clicking the individual buttons. 115 | At the bottom you have two joystick's, the left one is for walking and the right one for head movements. 116 | 117 | On the second page you are able to control each servo separately or together if you check the checkbox on the left. 118 | At the bottom you can send direct commands followed by the enter key. 119 | 120 | They are some experimental features that are not working satisfying at the moment because of limitation in the serial communication. 121 | - Auto update 122 | - If checked, updates from another page or movements from IR remote will be reflected here 123 | - Lazy update 124 | - If unchecked, updates will occur immediately during slider movements 125 | 126 | 127 | #### Library 128 | If you want to create your own application you can use the `ocw.api.js` library. 129 | Every method returns a jQuery promise object. 130 | ``` js 131 | let api = ocw.Api(); 132 | api.command('ksit').done((data) => { 133 | log.debug(data); 134 | }); 135 | ``` 136 | The library is not final and there is no further documentation about this. 137 | For examples just check the code in `ocw.main.js`. 138 | 139 | ### Examples (Nybble) 140 | You can use your `web browser`, `wget` or any other `script` to make the request. 141 | 142 | Meow twice: 143 | 144 | http://:8080/api/communicate/u/1/10 145 | 146 | Tilt head: 147 | 148 | http://:8080/api/move/m/1/0 149 | 150 | Tilt and pan head: 151 | 152 | http://:8080/api/move/i/0/0/1/0 153 | 154 | Stand up: 155 | 156 | http://:8080/api/command/kbalance 157 | 158 | With the `/api/command/` you can send any command you like, also custom one's. 159 | 160 | 161 | ## Known Issues 162 | - API 163 | - Unauthenticated and unencrypted Web API (use it only in your private network) 164 | - No upper/lower bound value validations (know what you send) 165 | - WEB 166 | - Experimental functions are lagging in time 167 | - Source code is uncommented 168 | 169 | 170 | ## Changelog 171 | > v0.3 - 2019-07-30 172 | - WEB 173 | - Add mimimum/maximum value validations 174 | > v0.2 - 2019-07-29 175 | - API 176 | - Improve multiple request's behavior 177 | - WEB 178 | - Add navigation menu 179 | - Add command buttons 180 | - Add joystick control 181 | > v0.1 - 2019-07-20 182 | - Initial release 183 | 184 | 185 | ## Thanks to 186 | - Rongzhong, for the awesome OpenCat project and the allowance to use the Petoi logo 187 | - Zaghaim, for the code in ardSerial.py that inspired me for the serial communication implementation 188 | 189 | ## License 190 | [MIT](https://github.com/leukipp/OpenCatWeb/blob/master/LICENSE) 191 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import cgi 4 | 5 | from flask import Flask, jsonify 6 | from bus import Serial, SerialCommand 7 | 8 | HOST = '0.0.0.0' 9 | PORT = 8080 10 | DEBUG = False 11 | 12 | app = Flask(__name__, static_folder = 'web') 13 | serial = Serial() 14 | 15 | 16 | @app.route('/') 17 | def root(): 18 | return links(['/web/', '/api/'], True) 19 | 20 | 21 | @app.route('/web/') 22 | def web(): 23 | return app.send_static_file('main.html') 24 | 25 | 26 | @app.route('/api/') 27 | def api(): 28 | return links(['/api/command/', '/api/communicate/', '/api/move/', '/api/stop/', '/api/status/'], True) 29 | 30 | 31 | @app.route('/api/command/') 32 | def api_command(): 33 | return links(['/api/command/'], False) 34 | 35 | 36 | @app.route('/api/command/') 37 | def api_command_value(name): 38 | return jsonify({'command': {name: serial.write(SerialCommand(name))}}) 39 | 40 | 41 | @app.route('/api/communicate/') 42 | def api_communicate(): 43 | return links(['/api/communicate/u/', '/api/communicate/b/'], True) 44 | 45 | 46 | @app.route('/api/communicate/u/') 47 | def api_communicate_u(): 48 | return links(['/api/communicate/u//'], False) 49 | 50 | 51 | @app.route('/api/communicate/u//') 52 | def api_communicate_u_repeat(repeat): 53 | return links(['/api/communicate/u/%i/' % repeat], False) 54 | 55 | 56 | @app.route('/api/communicate/u//') 57 | def api_communicate_u_repeat_tempo(repeat, tempo): 58 | return jsonify({'communicate': {'u': serial.write(SerialCommand('u', repeat, tempo))}}) 59 | 60 | 61 | @app.route('/api/communicate/b/') 62 | def api_communicate_b(): 63 | return links(['/api/communicate/b//'], False) 64 | 65 | 66 | @app.route('/api/communicate/b//') 67 | def api_communicate_b_note(note): 68 | return links(['/api/communicate/u/%i/' % note], False) 69 | 70 | 71 | @app.route('/api/communicate/b//') 72 | def api_communicate_b_note_duration(note, duration): 73 | return jsonify({'communicate': {'b': serial.write(SerialCommand('b', note, duration))}}) 74 | 75 | 76 | @app.route('/api/move/') 77 | def api_move(): 78 | return links(['/api/move/m/', '/api/move/i/', '/api/move/l/'], True) 79 | 80 | 81 | @app.route('/api/move/m/') 82 | def api_move_m(): 83 | return links(['/api/move/m//'], False) 84 | 85 | 86 | @app.route('/api/move/m//') 87 | def api_move_m_index(index): 88 | return links(['/api/move/m/%i/' % index], False) 89 | 90 | 91 | @app.route('/api/move/m//') 92 | def api_move_m_index_value(index, value): 93 | return jsonify({'move': {'m': serial.write(SerialCommand('m', index, int(value)))}}) 94 | 95 | 96 | @app.route('/api/move/i/') 97 | def api_move_i(): 98 | return links(['/api/move/i/////...'], False) 99 | 100 | 101 | @app.route('/api/move/i//') 102 | def api_move_i_indexvalue(indexvalue): 103 | args = map(int, indexvalue.split('/')) 104 | if len(args) % 2 == 0: 105 | return jsonify({'move': {'i': serial.write(SerialCommand('i', *args))}}) 106 | else: 107 | return links(['/api/move/i/%s/' % indexvalue], False) 108 | 109 | 110 | @app.route('/api/move/l/') 111 | def api_move_l(): 112 | return links(['/api/move/l//.../'], False) 113 | 114 | 115 | @app.route('/api/move/l//') 116 | def api_move_l_valueofindex(valueofindex): 117 | args = map(int, valueofindex.split('/')) 118 | if len(args) == 16: 119 | return jsonify({'move': {'l': serial.write(SerialCommand('l', *args))}}) 120 | else: 121 | return links(['/api/move/l/%s%s' % (valueofindex, '/' if len(args) == 15 else '.../')], 122 | False) 123 | 124 | 125 | @app.route('/api/stop/') 126 | def api_stop(): 127 | return links(['/api/stop/d', '/api/stop/p', '/api/stop/r'], True) 128 | 129 | 130 | @app.route('/api/stop/d/') 131 | def api_stop_d(): 132 | return jsonify({'stop': {'d': serial.write(SerialCommand('d'))}}) 133 | 134 | 135 | @app.route('/api/stop/p/') 136 | def api_stop_p(): 137 | return jsonify({'stop': {'p': serial.write(SerialCommand('p'))}}) 138 | 139 | 140 | @app.route('/api/stop/r/') 141 | def api_stop_r(): 142 | return jsonify({'stop': {'r': serial.write(SerialCommand('r'))}}) 143 | 144 | 145 | @app.route('/api/status/') 146 | def api_status(): 147 | return links(['/api/status/j'], True) 148 | 149 | 150 | @app.route('/api/status/j/') 151 | def api_status_j(): 152 | return jsonify({'status': {'j': serial.write(SerialCommand('j'))}}) 153 | 154 | 155 | def links(items, linked): 156 | ul = ['
    '] 157 | for item in items: 158 | ul.append('
  • ') 159 | if linked: 160 | ul.append('%s' % (item, cgi.escape(item))) 161 | else: 162 | ul.append(cgi.escape(item)) 163 | ul.append('
  • ') 164 | ul.append('
') 165 | return html(''.join(ul)) 166 | 167 | 168 | def html(body): 169 | return ''.join(['', 170 | '', 171 | '', 172 | '', 173 | '', 174 | 'OpenCatWeb', 175 | '', 176 | '', 177 | '', 178 | '', 179 | '', 180 | body, 181 | '', 182 | '' 183 | ]) 184 | 185 | 186 | if __name__ == '__main__': 187 | app.run( 188 | host = HOST, 189 | port = PORT, 190 | debug = DEBUG 191 | ) 192 | -------------------------------------------------------------------------------- /bus.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import serial 4 | import threading 5 | import struct 6 | import time 7 | 8 | 9 | class Serial: 10 | def __init__(self): 11 | self.lock = threading.Lock() 12 | self.connection = serial.Serial( 13 | port = '/dev/ttyAMA0', 14 | baudrate = 57600, 15 | parity = serial.PARITY_NONE, 16 | stopbits = serial.STOPBITS_ONE, 17 | bytesize = serial.EIGHTBITS, 18 | timeout = 1 19 | ) 20 | 21 | def write(self, command): 22 | with self.lock: 23 | print('-> %s' % str(command)) 24 | self.connection.write(str(command)) 25 | return self.read() if command.replies() else time.sleep(0.05) 26 | 27 | def read(self): 28 | retry = 0 29 | self.connection.reset_input_buffer() 30 | while retry < 1000: 31 | if self.connection.in_waiting > 0: 32 | line = self.connection.readline().strip() 33 | if '\t' in line: 34 | print(line) 35 | return line.split('\t') 36 | time.sleep(0.05) 37 | retry += 1 38 | 39 | 40 | class SerialCommand: 41 | def __init__(self, name, *args): 42 | self.token = name[0] 43 | self.name = name 44 | self.args = args 45 | 46 | def __str__(self): 47 | if self.token in ['l', 'i']: 48 | return self.name + struct.pack('b' * len(self.args), *self.args) 49 | else: 50 | return self.name + ' '.join(list(map(str, self.args))) 51 | 52 | def replies(self): 53 | return self.token in ['j'] 54 | -------------------------------------------------------------------------------- /ocw.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: ocw 5 | # Required-Start: $remote_fs $syslog 6 | # Required-Stop: $remote_fs $syslog 7 | # Default-Start: 2 3 4 5 8 | # Default-Stop: 0 1 6 9 | # Short-Description: Start OpenCatWeb at boot time 10 | # Description: Start flask webserver for OpenCatWeb 11 | ### END INIT INFO 12 | 13 | DAEMON=/home/pi/Projects/OpenCatWeb/app.py 14 | DAEMON_NAME=ocw 15 | DAEMON_USER=root 16 | 17 | PIDFILE=/var/run/$DAEMON_NAME.pid 18 | . /lib/lsb/init-functions 19 | 20 | do_start() { 21 | log_daemon_msg "Starting system $DAEMON_NAME daemon" 22 | start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON 23 | log_end_msg $? 24 | } 25 | 26 | do_stop() { 27 | log_daemon_msg "Stopping system $DAEMON_NAME daemon" 28 | start-stop-daemon --stop --pidfile $PIDFILE --retry 10 29 | log_end_msg $? 30 | } 31 | 32 | case "$1" in 33 | start|stop) 34 | do_${1} 35 | ;; 36 | restart|reload|force-reload) 37 | do_stop 38 | do_start 39 | ;; 40 | status) 41 | status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $? 42 | ;; 43 | *) 44 | echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}" 45 | exit 1 46 | ;; 47 | esac 48 | exit 0 49 | -------------------------------------------------------------------------------- /web/css/ocw.main.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | font: 16px Helvetica; 3 | height: 100%; 4 | overflow: hidden; 5 | width: 100%; 6 | } 7 | 8 | ul { 9 | list-style-type: none; 10 | } 11 | 12 | li { 13 | border-bottom: 1px solid #f6f6f6; 14 | cursor: default; 15 | line-height: 24px; 16 | padding: 5px; 17 | } 18 | 19 | li a { 20 | color: #000000; 21 | cursor: pointer; 22 | display: block; 23 | text-decoration: none; 24 | transition: font-size 0.3s ease, background-color 0.3s ease; 25 | width: 100%; 26 | } 27 | 28 | li a:hover { 29 | background: #f6f6f6; 30 | font-size: 20px; 31 | } 32 | 33 | #app { 34 | height: 100%; 35 | overflow: hidden; 36 | width: 100%; 37 | } 38 | 39 | #menu { 40 | box-sizing: border-box; 41 | font-size: 26px; 42 | height: 44px; 43 | left: 8px; 44 | position: absolute; 45 | text-align: center; 46 | top: 8px; 47 | width: 44px; 48 | z-index: 1000; 49 | } 50 | 51 | #menu-open { 52 | display: none; 53 | } 54 | 55 | .menu-open-button { 56 | background: #f6f6f6; 57 | border-radius: 100%; 58 | cursor: pointer; 59 | height: 44px; 60 | margin-left: -22px; 61 | position: absolute; 62 | text-align: center; 63 | transform: scale(1, 1) translate3d(0, 0, 0); 64 | transition: transform ease-out 200ms; 65 | transition-duration: 400ms; 66 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275); 67 | width: 44px; 68 | z-index: 100; 69 | } 70 | 71 | .menu-open-button:hover { 72 | transform: scale(1.2, 1.2) translate3d(0, 0, 0); 73 | } 74 | 75 | .menu-line { 76 | background: #666666; 77 | display: block; 78 | height: 3px; 79 | left: 50%; 80 | margin-left: -12.5px; 81 | margin-top: -1.5px; 82 | position: absolute; 83 | top: 50%; 84 | transition: transform 200ms; 85 | width: 25px; 86 | } 87 | 88 | .menu-line.line-1 { 89 | transform: translate3d(0, -8px, 0); 90 | } 91 | 92 | .menu-line.line-2 { 93 | transform: translate3d(0, 0, 0); 94 | } 95 | 96 | .menu-line.line-3 { 97 | transform: translate3d(0, 8px, 0); 98 | } 99 | 100 | #menu-open:checked + .menu-open-button .line-1 { 101 | transform: translate3d(0, 0, 0) rotate(45deg); 102 | } 103 | 104 | #menu-open:checked + .menu-open-button .line-2 { 105 | transform: translate3d(0, 0, 0) scale(0.1, 1); 106 | } 107 | 108 | #menu-open:checked + .menu-open-button .line-3 { 109 | transform: translate3d(0, 0, 0) rotate(-45deg); 110 | } 111 | 112 | #menu-open:checked + .menu-open-button { 113 | transform: scale(0.8, 0.8) translate3d(0, 0, 0); 114 | transition-duration: 200ms; 115 | transition-timing-function: linear; 116 | } 117 | 118 | #menu-open:checked ~ .menu-item { 119 | box-shadow: 3px 3px 0 0 rgba(0, 0, 0, 0.14); 120 | text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.12); 121 | transition-timing-function: cubic-bezier(0.935, 0, 0.34, 1.33); 122 | } 123 | 124 | #menu-open:checked ~ .menu-item.item-1 { 125 | transform: translate3d(80px, 0px, 0); 126 | transition-duration: 180ms; 127 | } 128 | 129 | #menu-open:checked ~ .menu-item.item-1:hover { 130 | transform: scale(1.2, 1.2) translate3d(64px, 0px, 0); 131 | } 132 | 133 | #menu-open:checked ~ .menu-item.item-2 { 134 | transform: translate3d(56.56px, 56.56px, 0); 135 | transition-duration: 280ms; 136 | } 137 | 138 | #menu-open:checked ~ .menu-item.item-2:hover { 139 | transform: scale(1.2, 1.2) translate3d(45.248px, 45.248px, 0); 140 | transform-origin: 50% 50%; 141 | } 142 | 143 | #menu-open:checked ~ .menu-item.item-3 { 144 | transform: translate3d(0px, 80px, 0); 145 | transition-duration: 380ms; 146 | } 147 | 148 | #menu-open:checked ~ .menu-item.item-3:hover { 149 | transform: scale(1.2, 1.2) translate3d(0px, 64px, 0); 150 | } 151 | 152 | .menu-item { 153 | border-radius: 100%; 154 | color: #ffffff; 155 | cursor: pointer; 156 | height: 40px; 157 | line-height: 40px; 158 | margin: 2px 0px 0px -20px; 159 | position: absolute; 160 | text-align: center; 161 | transition: transform ease-out 200ms; 162 | width: 40px; 163 | z-index: 10; 164 | } 165 | 166 | .menu-item.item-1 { 167 | background-color: #3498db; 168 | } 169 | 170 | .menu-item.item-2 { 171 | background-color: #ffc102; 172 | } 173 | 174 | .menu-item.item-3 { 175 | background-color: #fe4365; 176 | } 177 | 178 | .page { 179 | height: 100%; 180 | width: 100%; 181 | } 182 | 183 | #status { 184 | background: #f6f6f6; 185 | height: 60px; 186 | width: 100%; 187 | } 188 | 189 | #buttons { 190 | height: calc(100% - 200px); 191 | margin: auto; 192 | max-width: 500px; 193 | } 194 | 195 | .button { 196 | cursor: pointer; 197 | float: left; 198 | height: calc(25% - 20px); 199 | margin: 10px; 200 | min-height: 20px; 201 | position: relative; 202 | text-align: center; 203 | user-select: none; 204 | width: calc(33% - 20px); 205 | } 206 | 207 | .button::before { 208 | background: linear-gradient(135deg, #6e8efb, #a777e3); 209 | border-radius: 4px; 210 | bottom: 0; 211 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); 212 | content: ''; 213 | left: 0; 214 | position: absolute; 215 | right: 0; 216 | top: 0; 217 | transition: box-shadow .5s ease, transform .2s ease; 218 | will-change: transform; 219 | } 220 | 221 | .button:hover::before { 222 | box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); 223 | } 224 | 225 | .button::after { 226 | content: attr(data-title); 227 | display: inline-block; 228 | font-weight: bold; 229 | letter-spacing: .01em; 230 | position: relative; 231 | transition: transform .2s ease; 232 | will-change: transform; 233 | } 234 | 235 | .button:nth-child(3n + 1) { 236 | clear: left 237 | } 238 | 239 | .button .name { 240 | color: #ffffff; 241 | font-size: 22px; 242 | left: 50%; 243 | position: absolute; 244 | text-transform: uppercase; 245 | top: 50%; 246 | transform: translate(-50%, -50%); 247 | white-space: nowrap; 248 | } 249 | 250 | #controller { 251 | background: #f6f6f6; 252 | bottom: 0px; 253 | height: 140px; 254 | left: 0px; 255 | position: absolute; 256 | right: 0px; 257 | width: 100%; 258 | } 259 | 260 | .actions { 261 | left: 50%; 262 | margin: auto; 263 | position: absolute; 264 | text-align: center; 265 | top: 0px; 266 | transform: translate(-50%, 0); 267 | z-index: 100; 268 | } 269 | 270 | .action { 271 | color: #666666; 272 | cursor: pointer; 273 | display: inline-block; 274 | padding: 10px; 275 | } 276 | 277 | .joysticks { 278 | height: 100%; 279 | margin: auto; 280 | max-width: 600px; 281 | position: relative; 282 | } 283 | 284 | .joystick { 285 | height: 100%; 286 | position: absolute; 287 | width: 50%; 288 | } 289 | 290 | .joystick .front { 291 | cursor: pointer; 292 | opacity: 0.9 !important; 293 | } 294 | 295 | .joystick .back { 296 | opacity: 0.6 !important; 297 | } 298 | 299 | #left { 300 | left: 0px; 301 | top: 0px; 302 | } 303 | 304 | #right { 305 | right: 0px; 306 | top: 0px; 307 | } 308 | 309 | #settings { 310 | background: #f6f6f6; 311 | padding: 6px; 312 | } 313 | 314 | .setting { 315 | line-height: 24px; 316 | margin: 0px auto; 317 | max-width: 300px; 318 | text-align: center; 319 | } 320 | 321 | #sliders { 322 | height: calc(100% - 119px); 323 | margin: auto; 324 | overflow-y: scroll; 325 | } 326 | 327 | .slider { 328 | margin: 20px auto; 329 | max-width: 300px; 330 | position: relative; 331 | } 332 | 333 | .slider.inactive { 334 | display: none; 335 | } 336 | 337 | #commands { 338 | background: #f6f6f6; 339 | bottom: 0px; 340 | left: 0px; 341 | padding: 10px; 342 | position: absolute; 343 | right: 0px; 344 | text-align: center; 345 | z-index: 10; 346 | } 347 | 348 | .command { 349 | border: none; 350 | font-size: 16px; 351 | margin: 5px auto; 352 | padding: 5px; 353 | width: 300px; 354 | } 355 | 356 | .more { 357 | color: #666666; 358 | left: 50%; 359 | position: absolute; 360 | top: 50%; 361 | transform: translate(-50%, -50%); 362 | } 363 | 364 | -------------------------------------------------------------------------------- /web/css/reset.css: -------------------------------------------------------------------------------- 1 | /* 2 | html5doctor.com Reset Stylesheet 3 | v1.6.1 4 | Last Updated: 2010-09-17 5 | Author: Richard Clark - http://richclarkdesign.com 6 | Twitter: @rich_clark 7 | */ 8 | 9 | html, body, div, span, object, iframe, 10 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 11 | abbr, address, cite, code, 12 | del, dfn, em, img, ins, kbd, q, samp, 13 | small, strong, sub, sup, var, 14 | b, i, 15 | dl, dt, dd, ol, ul, li, 16 | fieldset, form, label, legend, 17 | table, caption, tbody, tfoot, thead, tr, th, td, 18 | article, aside, canvas, details, figcaption, figure, 19 | footer, header, hgroup, menu, nav, section, summary, 20 | time, mark, audio, video { 21 | margin: 0; 22 | padding: 0; 23 | border: 0; 24 | outline: 0; 25 | font-size: 100%; 26 | vertical-align: baseline; 27 | background: transparent; 28 | } 29 | 30 | body { 31 | line-height: 1; 32 | } 33 | 34 | article, aside, details, figcaption, figure, 35 | footer, header, hgroup, menu, nav, section { 36 | display: block; 37 | } 38 | 39 | nav ul { 40 | list-style: none; 41 | } 42 | 43 | blockquote, q { 44 | quotes: none; 45 | } 46 | 47 | blockquote:before, blockquote:after, 48 | q:before, q:after { 49 | content: ''; 50 | content: none; 51 | } 52 | 53 | a { 54 | margin: 0; 55 | padding: 0; 56 | font-size: 100%; 57 | vertical-align: baseline; 58 | background: transparent; 59 | } 60 | 61 | /* change colours to suit your needs */ 62 | ins { 63 | background-color: #ff9; 64 | color: #000; 65 | text-decoration: none; 66 | } 67 | 68 | /* change colours to suit your needs */ 69 | mark { 70 | background-color: #ff9; 71 | color: #000; 72 | font-style: italic; 73 | font-weight: bold; 74 | } 75 | 76 | del { 77 | text-decoration: line-through; 78 | } 79 | 80 | abbr[title], dfn[title] { 81 | border-bottom: 1px dotted; 82 | cursor: help; 83 | } 84 | 85 | table { 86 | border-collapse: collapse; 87 | border-spacing: 0; 88 | } 89 | 90 | /* change border colour to suit your needs */ 91 | hr { 92 | display: block; 93 | height: 1px; 94 | border: 0; 95 | border-top: 1px solid #cccccc; 96 | margin: 1em 0; 97 | padding: 0; 98 | } 99 | 100 | input, select { 101 | vertical-align: middle; 102 | } 103 | -------------------------------------------------------------------------------- /web/css/vue.slider.css: -------------------------------------------------------------------------------- 1 | /* component style */ 2 | .vue-slider-disabled { 3 | opacity: 0.5; 4 | cursor: not-allowed; 5 | } 6 | 7 | /* rail style */ 8 | .vue-slider-rail { 9 | background-color: #ccc; 10 | border-radius: 15px; 11 | } 12 | 13 | /* process style */ 14 | .vue-slider-process { 15 | background-color: #3498db; 16 | border-radius: 15px; 17 | } 18 | 19 | /* mark style */ 20 | .vue-slider-mark { 21 | z-index: 4; 22 | } 23 | 24 | .vue-slider-mark:first-child .vue-slider-mark-step, .vue-slider-mark:last-child .vue-slider-mark-step { 25 | display: none; 26 | } 27 | 28 | .vue-slider-mark-step { 29 | width: 100%; 30 | height: 100%; 31 | border-radius: 50%; 32 | background-color: rgba(0, 0, 0, 0.16); 33 | } 34 | 35 | .vue-slider-mark-label { 36 | font-size: 14px; 37 | white-space: nowrap; 38 | } 39 | 40 | /* dot style */ 41 | .vue-slider-dot-handle { 42 | cursor: pointer; 43 | width: 100%; 44 | height: 100%; 45 | border-radius: 50%; 46 | background-color: #fff; 47 | box-sizing: border-box; 48 | box-shadow: 0.5px 0.5px 2px 1px rgba(0, 0, 0, 0.32); 49 | } 50 | 51 | .vue-slider-dot-handle-focus { 52 | box-shadow: 0px 0px 1px 2px rgba(52, 152, 219, 0.36); 53 | } 54 | 55 | .vue-slider-dot-handle-disabled { 56 | cursor: not-allowed; 57 | background-color: #ccc; 58 | } 59 | 60 | .vue-slider-dot-tooltip-inner { 61 | font-size: 14px; 62 | white-space: nowrap; 63 | padding: 2px 5px; 64 | min-width: 20px; 65 | text-align: center; 66 | color: #fff; 67 | border-radius: 5px; 68 | border-color: #3498db; 69 | background-color: #3498db; 70 | box-sizing: content-box; 71 | } 72 | 73 | .vue-slider-dot-tooltip-inner::after { 74 | content: ""; 75 | position: absolute; 76 | } 77 | 78 | .vue-slider-dot-tooltip-inner-top::after { 79 | top: 100%; 80 | left: 50%; 81 | transform: translate(-50%, 0); 82 | height: 0; 83 | width: 0; 84 | border-color: transparent; 85 | border-style: solid; 86 | border-width: 5px; 87 | border-top-color: inherit; 88 | } 89 | 90 | .vue-slider-dot-tooltip-inner-bottom::after { 91 | bottom: 100%; 92 | left: 50%; 93 | transform: translate(-50%, 0); 94 | height: 0; 95 | width: 0; 96 | border-color: transparent; 97 | border-style: solid; 98 | border-width: 5px; 99 | border-bottom-color: inherit; 100 | } 101 | 102 | .vue-slider-dot-tooltip-inner-left::after { 103 | left: 100%; 104 | top: 50%; 105 | transform: translate(0, -50%); 106 | height: 0; 107 | width: 0; 108 | border-color: transparent; 109 | border-style: solid; 110 | border-width: 5px; 111 | border-left-color: inherit; 112 | } 113 | 114 | .vue-slider-dot-tooltip-inner-right::after { 115 | right: 100%; 116 | top: 50%; 117 | transform: translate(0, -50%); 118 | height: 0; 119 | width: 0; 120 | border-color: transparent; 121 | border-style: solid; 122 | border-width: 5px; 123 | border-right-color: inherit; 124 | } 125 | 126 | .vue-slider-dot-tooltip-wrapper { 127 | opacity: 0; 128 | transition: all 0.3s; 129 | } 130 | 131 | .vue-slider-dot-tooltip-wrapper-show { 132 | opacity: 1; 133 | } 134 | 135 | /*# sourceMappingURL=default.css.map */ 136 | -------------------------------------------------------------------------------- /web/fonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leukipp/opencat-web/37e3c34073bec4e5f923686b02115615fb4f47f8/web/fonts/fa-solid-900.eot -------------------------------------------------------------------------------- /web/fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leukipp/opencat-web/37e3c34073bec4e5f923686b02115615fb4f47f8/web/fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /web/fonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leukipp/opencat-web/37e3c34073bec4e5f923686b02115615fb4f47f8/web/fonts/fa-solid-900.woff -------------------------------------------------------------------------------- /web/fonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leukipp/opencat-web/37e3c34073bec4e5f923686b02115615fb4f47f8/web/fonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /web/img/api.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leukipp/opencat-web/37e3c34073bec4e5f923686b02115615fb4f47f8/web/img/api.gif -------------------------------------------------------------------------------- /web/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leukipp/opencat-web/37e3c34073bec4e5f923686b02115615fb4f47f8/web/img/favicon.png -------------------------------------------------------------------------------- /web/img/web.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leukipp/opencat-web/37e3c34073bec4e5f923686b02115615fb4f47f8/web/img/web.gif -------------------------------------------------------------------------------- /web/js/jquery.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0e;e+=1)if(i.nipples[e].identifier===t)return i.nipples[e]},"static"===i.options.mode){var e=this.createNipple(this.options.position,0);e.add()}var o;return window.onresize=function(t){clearTimeout(o),o=setTimeout(function(){var t,e=h.getScroll();i.nipples.forEach(function(i){t=i.el.getBoundingClientRect(),i.position={x:e.x+t.left,y:e.y+t.top}})},100)},i.nipples}var e,o=!!("ontouchstart"in window),n=window.PointerEvent?!0:!1,s=window.MSPointerEvent?!0:!1,r={touch:{start:"touchstart",move:"touchmove",end:"touchend"},mouse:{start:"mousedown",move:"mousemove",end:"mouseup"},pointer:{start:"pointerdown",move:"pointermove",end:"pointerup"},MSPointer:{start:"MSPointerDown",move:"MSPointerMove",end:"MSPointerUp"}},p={},a={};n?e=r.pointer:s?e=r.MSPointer:o?(e=r.touch,a=r.mouse):e=r.mouse;var h={};h.distance=function(t,i){var e=i.x-t.x,o=i.y-t.y;return Math.sqrt(e*e+o*o)},h.angle=function(t,i){var e=i.x-t.x,o=i.y-t.y;return h.degrees(Math.atan2(o,e))},h.findCoord=function(t,i,e){var o={x:0,y:0};return e=h.radians(e),o.x=t.x-i*Math.cos(e),o.y=t.y-i*Math.sin(e),o},h.radians=function(t){return t*(Math.PI/180)},h.degrees=function(t){return t*(180/Math.PI)},h.bindEvt=function(t,i,e){t.addEventListener?t.addEventListener(i,e,!1):t.attachEvent&&t.attachEvent(i,e)},h.unbindEvt=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e):t.detachEvent&&t.detachEvent(i,e)},h.trigger=function(t,i,e){var o=new CustomEvent(i,e);t.dispatchEvent(o)},h.prepareEvent=function(t){return t.preventDefault(),t.type.match(/^touch/)?t.changedTouches:t},h.getScroll=function(){var t=void 0!==window.pageXOffset?window.pageXOffset:(document.documentElement||document.body.parentNode||document.body).scrollLeft,i=void 0!==window.pageYOffset?window.pageYOffset:(document.documentElement||document.body.parentNode||document.body).scrollTop;return{x:t,y:i}},h.applyPosition=function(t,i){i.x&&i.y?(t.style.left=i.x+"px",t.style.top=i.y+"px"):(i.top||i.right||i.bottom||i.left)&&(t.style.top=i.top,t.style.right=i.right,t.style.bottom=i.bottom,t.style.left=i.left)},h.getTransitionStyle=function(t,i,e){var o=h.configStylePropertyObject(t);for(var n in o)if(o.hasOwnProperty(n))if("string"==typeof i)o[n]=i+" "+e;else{for(var s="",r=0,p=i.length;p>r;r+=1)s+=i[r]+" "+e+", ";o[n]=s.slice(0,-2)}return o},h.getVendorStyle=function(t,i){var e=h.configStylePropertyObject(t);for(var o in e)e.hasOwnProperty(o)&&(e[o]=i);return e},h.configStylePropertyObject=function(t){var i={};i[t]="";var e=["webkit","Moz","o"];return e.forEach(function(e){i[e+t.charAt(0).toUpperCase()+t.slice(1)]=""}),i},h.extend=function(t,i){for(var e in i)i.hasOwnProperty(e)&&(t[e]=i[e])};var d=function(){};return d.prototype.on=function(t,i){for(var e,o=this,n=t.split(/[ ,]+/g),s=0;s=0&&e.handlers[t].splice(e.handlers[t].indexOf(i),1),e},d.prototype.trigger=function(t,i){for(var e,o=this,n=t.split(/[ ,]+/g),s=0;ss&&3*s>n?"up":n>-s&&s>=n?"left":n>3*-s&&-s>=n?"down":"right",e=n>-r&&r>n?"left":"right",o=n>0?"up":"down",t.force>this.options.threshold){var p={};for(var a in this.direction)this.direction.hasOwnProperty(a)&&(p[a]=this.direction[a]);var h=!0;this.direction={x:e,y:o,angle:i},t.direction=this.direction;for(var a in p)p[a]!==this.direction[a]&&(h=!1);if(h)return t;(p.x!==this.direction.x||p.y!==this.direction.y)&&(this.trigger("plain",t),this.manager.trigger("plain "+this.identifier+":plain",t)),p.x!==this.direction.x&&(this.trigger("plain:"+e,t),this.manager.trigger("plain:"+e+" "+this.identifier+":plain:"+e,t)),p.y!==this.direction.y&&(this.trigger("plain:"+o,t),this.manager.trigger("plain:"+o+" "+this.identifier+":plain:"+o,t)),p.angle!==this.direction.angle&&(this.trigger("dir dir:"+i,t),this.manager.trigger("dir dir:"+i+" "+this.identifier+":dir "+this.identifier+":dir:"+i,t))}return t},i.prototype=new d,i.constructor=i,i.prototype.config=function(t){this.options={},this.nippleOptions={},this.options.zone=document.body,this.options.multitouch=!1,this.options.maxNumberOfNipples=1,this.options.mode="dynamic",this.options.position={top:0,left:0},this.options.catchDistance=200,this.nippleOptions.size=100,this.nippleOptions.threshold=.1,this.nippleOptions.color="white",this.nippleOptions.fadeTime=250,this.nippleOptions.dataOnly=!1,this.nippleOptions.restOpacity=.5,this.nippleOptions.mode=this.options.mode;for(var i in t)this.options.hasOwnProperty(i)?this.options[i]=t[i]:this.nippleOptions.hasOwnProperty(i)&&(this.nippleOptions[i]=t[i]);return("static"===this.options.mode||"semi"===this.options.mode)&&(this.options.multitouch=!1,this.options.maxNumberOfNipples=1),this},i.prototype.createNipple=function(i,e){var o=h.getScroll(),n={};if(i.x&&i.y)n={x:i.x-(o.x+this.box.left),y:i.y-(o.y+this.box.top)};else if(i.top||i.right||i.bottom||i.left){var s=document.createElement("DIV");s.style.display="hidden",s.style.top=i.top,s.style.right=i.right,s.style.bottom=i.bottom,s.style.left=i.left,s.style.position="absolute",this.options.zone.appendChild(s);var r=s.getBoundingClientRect();this.options.zone.removeChild(s),n=i,i={x:r.left+o.x,y:r.top+o.y}}var p={x:0,y:0},a=new t(this,{color:this.nippleOptions.color,size:this.nippleOptions.size,threshold:this.nippleOptions.threshold,fadeTime:this.nippleOptions.fadeTime,dataOnly:this.nippleOptions.dataOnly,restOpacity:this.nippleOptions.restOpacity,mode:this.options.mode,identifier:e,position:i,frontPosition:p});return this.nippleOptions.dataOnly||(h.applyPosition(a.ui.el,n),h.applyPosition(a.ui.front,a.frontPosition)),this.nipples.push(a),a},i.prototype.bindEvt=function(t,i){var o=this;return p[i]=function(){o["on"+i].apply(o,arguments)},h.bindEvt(t,e[i],p[i]),a[i]&&h.bindEvt(t,a[i],p[i]),o},i.prototype.unbindEvt=function(t,i){return h.unbindEvt(t,e[i],p[i]),a[i]&&h.unbindEvt(t,a[i],p[i]),p[i]=void 0,this},i.prototype.onstart=function(t){if(t=h.prepareEvent(t),this.box=this.options.zone.getBoundingClientRect(),this.scroll=h.getScroll(),t.length&&this.options.multitouch&&this.nipples.lengthi;i+=1)this.processOnStart(t[i]);else(0===this.nipples.length||"dynamic"!==this.options.mode)&&this.processOnStart(t[0]||t);return this.started||(this.bindEvt(document,"move").bindEvt(document,"end"),this.started=!0),!1},i.prototype.pressureFn=function(t,i,e){var o=0;clearInterval(this.pressureIntervals[e]),this.pressureIntervals[e]=setInterval(function(){var e=t.force||t.pressure||t.webkitForce||0;e!==o&&(i.trigger("pressure",e),this.trigger("pressure "+i.identifier+":pressure",e),o=e)}.bind(this),100)},i.prototype.processOnStart=function(t){var i=(void 0!==t.identifier?t.identifier:t.pointerId)||0,e=t.force||t.pressure||t.webkitForce||0,o=this.nipples.get(i),n={x:t.pageX,y:t.pageY};if(o){if("static"===this.options.mode&&(o.show(),e>0&&this.pressureFn(t,o,i),this.processOnMove(t)),"semi"===this.options.mode){var s=h.distance(n,o.position);s<=this.options.catchDistance?(o.show(),e>0&&this.pressureFn(t,o,i),this.processOnMove(t)):(o.destroy(),this.processOnStart(t))}}else o=this.createNipple(n,i),this.trigger("added "+o.identifier+":added",o),o.show(),e>0&&this.pressureFn(t,o,i);return o.trigger("start",o),this.trigger("start "+o.identifier+":start",o),o},i.prototype.onmove=function(t){t=h.prepareEvent(t);var i=[];if(t.length&&this.options.multitouch)for(var e=0,o=t.length;o>e;e+=1)i.push(this.processOnMove(t[e]));else i.push(this.processOnMove(t[0]||t));return!1},i.prototype.processOnMove=function(t){var i=(void 0!==t.identifier?t.identifier:t.pointerId)||0,e=this.nipples.get(i);if(!e)return console.error("MOVE: Couldn't find the nipple n°"+i+"."),void console.error(this.nipples);var o=e.options.size/2,n={x:t.pageX,y:t.pageY},s=h.distance(n,e.position),r=h.angle(n,e.position),p=h.radians(r),a=s/o;s>o&&(s=o,n=h.findCoord(e.position,s,r)),e.frontPosition={x:n.x-e.position.x,y:n.y-e.position.y},this.nippleOptions.dataOnly||h.applyPosition(e.ui.front,e.frontPosition);var d={identifier:e.identifier,position:n,force:a,pressure:t.force||t.pressure||t.webkitForce||0,distance:s,angle:{radian:p,degree:r},instance:e};return d=e.computeDirection(d),d.angle={radian:h.radians(180-r),degree:180-r},e.trigger("move",d),this.trigger("move "+i+":move",d),d},i.prototype.onend=function(t){if(t=h.prepareEvent(t),t.length&&this.options.multitouch)for(var i=0,e=t.length;e>i;i+=1)this.processOnEnd(t[i]);else this.processOnEnd(t[0]||t);return this.nipples.length&&"dynamic"===this.options.mode||(this.unbindEvt(document,"move").unbindEvt(document,"end"),this.started=!1),!1},i.prototype.processOnEnd=function(t){var i=(void 0!==t.identifier?t.identifier:t.pointerId)||0,e=this,o=e.nipples.get(i);return o?(this.nippleOptions.dataOnly||o.hide(function(){"dynamic"===e.options.mode&&(o.trigger("removed",o),e.trigger("removed "+i+":removed",o),o.destroy())}),clearInterval(e.pressureIntervals[i]),o.trigger("end",o),e.trigger("end "+i+":end",o),void("dynamic"===this.options.mode&&this.nipples.splice(this.nipples.indexOf(o),1))):(console.error("END: Couldn't find the nipple n°"+i+"."),void console.error(e.nipples))},i.prototype.ondestroyed=function(t,i){return this.nipples.indexOf(i)<0?!1:void this.nipples.splice(this.nipples.indexOf(i),1)},i.prototype.destroy=function(){this.unbindEvt(this.options.zone,"start"),this.unbindEvt(document,"move"),this.unbindEvt(document,"end"),this.nipples.forEach(function(t){t.destroy()});for(var t in this.pressureIntervals)this.pressureIntervals.hasOwnProperty(t)&&clearInterval(this.pressureIntervals[t]);this.off()},{create:function(t){return new i(t)}}}); -------------------------------------------------------------------------------- /web/js/ocw.api.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | window.ocw = window.ocw || (() => {}); 4 | window.ocw.Api = (host, port) => { 5 | let log = ocw.Log(); 6 | 7 | let _request = (path, name, args) => { 8 | let base = host && port ? `http://${host}:${port}/api` : '/api'; 9 | let command = name + (Array.isArray(args) ? '/' + args.join('/') : ''); 10 | return $.ajax({ 11 | url: `${base}/${path}/${command}`, 12 | type: 'GET', 13 | dataType: 'json' 14 | }).fail(log.error); 15 | }; 16 | 17 | let _factory = (path, names) => { 18 | if (path == 'command') { 19 | return (name) => { 20 | return _request(path, name); 21 | }; 22 | } else { 23 | let methods = {}; 24 | names.forEach((name) => { 25 | methods[name] = (...args) => { 26 | return _request(path, name, args); 27 | }; 28 | }); 29 | return methods; 30 | } 31 | }; 32 | 33 | return { 34 | command: _factory('command'), 35 | communicate: _factory('communicate', ['u', 'b']), 36 | move: _factory('move', ['m', 'i', 'l']), 37 | stop: _factory('stop', ['d', 'p', 'r']), 38 | status: _factory('status', ['j']) 39 | }; 40 | }; 41 | 42 | window.ocw.Command = (command) => { 43 | let api = ocw.Api(); 44 | 45 | let _command = command || ''; 46 | 47 | let _setCommand = (command) => { 48 | _command = command ? command : _command; 49 | return _command; 50 | }; 51 | 52 | let _getCommand = () => { 53 | return _command; 54 | }; 55 | 56 | let _writeCommand = (command) => { 57 | return api.command(_setCommand(command)); 58 | }; 59 | 60 | return { 61 | setCommand: _setCommand, 62 | getCommand: _getCommand, 63 | writeCommand: _writeCommand 64 | }; 65 | }; 66 | 67 | window.ocw.communicate = window.ocw.communicate || (() => {}); 68 | window.ocw.communicate.U = () => { /* TODO */ }; 69 | window.ocw.communicate.B = () => { /* TODO */ }; 70 | 71 | window.ocw.move = window.ocw.move || (() => {}); 72 | window.ocw.move.M = (index, value) => { 73 | let api = ocw.Api(); 74 | 75 | let _index = index; 76 | let _value = value; 77 | 78 | let _setIndex = (index) => { 79 | _index = Number.isInteger(index) ? parseInt(index) : _index; 80 | return _index; 81 | }; 82 | 83 | let _getIndex = () => { 84 | return _index; 85 | }; 86 | 87 | let _setValue = (value) => { 88 | _value = Number.isInteger(value) ? parseInt(value) : _value; 89 | return _value; 90 | }; 91 | 92 | let _getValue = () => { 93 | return _value; 94 | }; 95 | 96 | let _writeValue = (value) => { 97 | return api.move.m(index, _setValue(value)); 98 | }; 99 | 100 | let _readValue = () => { 101 | let deferred = $.Deferred(); 102 | api.status.j().done((data) => { 103 | deferred.resolve(_setValue(data.status.j[index])); 104 | }); 105 | return deferred.promise(); 106 | }; 107 | 108 | return { 109 | setIndex: _setIndex, 110 | getIndex: _getIndex, 111 | setValue: _setValue, 112 | getValue: _getValue, 113 | writeValue: _writeValue, 114 | readValue: _readValue 115 | }; 116 | }; 117 | window.ocw.move.I = (...indexValue) => { 118 | let api = ocw.Api(); 119 | 120 | let _indexValue = indexValue || []; 121 | 122 | let _setIndexValue = (...indexValue) => { 123 | _indexValue = Array.isArray(indexValue) && indexValue.length ? indexValue.map(iv => parseInt(iv)) : _indexValue; 124 | return _indexValue; 125 | }; 126 | 127 | let _getIndexValue = (index) => { 128 | return Number.isInteger(index) ? _indexValue[index] : _indexValue; 129 | }; 130 | 131 | let _writeIndexValue = (...indexValue) => { 132 | return api.move.i(..._setIndexValue(...indexValue)); 133 | }; 134 | 135 | let _readIndexValue = () => { 136 | let deferred = $.Deferred(); 137 | api.status.j().done((data) => { 138 | deferred.resolve(_setIndexValue(...data.status.j)); 139 | }); 140 | return deferred.promise(); 141 | }; 142 | 143 | return { 144 | setIndexValue: _setIndexValue, 145 | getIndexValue: _getIndexValue, 146 | writeIndexValue: _writeIndexValue, 147 | readIndexValue: _readIndexValue 148 | }; 149 | }; 150 | window.ocw.move.L = () => { /* TODO */ }; 151 | 152 | window.ocw.stop = window.ocw.stop || (() => {}); 153 | window.ocw.stop.D = () => { /* TODO */ }; 154 | window.ocw.stop.P = () => { /* TODO */ }; 155 | window.ocw.stop.R = () => { /* TODO */ }; 156 | 157 | window.ocw.status = window.ocw.status || (() => {}); 158 | window.ocw.status.J = () => { 159 | let api = ocw.Api(); 160 | 161 | let _status = []; 162 | 163 | let _setStatus = (status) => { 164 | _status = Array.isArray(status) && status.length ? status.map(s => parseInt(s)) : _status; 165 | return _status; 166 | }; 167 | 168 | let _getStatus = () => { 169 | return _status; 170 | }; 171 | 172 | let _readStatus = () => { 173 | let deferred = $.Deferred(); 174 | api.status.j().done((data) => { 175 | deferred.resolve(_setStatus(data.status.j)); 176 | }); 177 | return deferred.promise(); 178 | }; 179 | 180 | return { 181 | getStatus: _getStatus, 182 | readStatus: _readStatus 183 | }; 184 | }; 185 | -------------------------------------------------------------------------------- /web/js/ocw.log.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | window.ocw = window.ocw || (() => {}); 4 | window.ocw.Log = () => { 5 | let _factory = (level) => { 6 | return (message) => { 7 | console[level](message && message.responseText ? $(/([\s\S]+)<\/body>/.exec(message.responseText)[0]).text() : message); 8 | }; 9 | }; 10 | 11 | return { 12 | error: _factory('error'), 13 | warn: _factory('warn'), 14 | info: _factory('info'), 15 | debug: _factory('debug') 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /web/js/ocw.main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let log = ocw.Log(); 4 | let api = ocw.Api(); 5 | 6 | let j = ocw.status.J(); 7 | j.readStatus().done((status) => { 8 | let m = status.map((value, index) => ocw.move.M(index, value)); 9 | 10 | let vue = new Vue({ 11 | el: '#app', 12 | data: () => { 13 | let data = { 14 | page: 1, 15 | menuOpen: false, 16 | menuOpenPage: (e) => { 17 | vue.$data.page = parseInt($(e.target).closest('.menu-item').attr('class').split('-')[2]); 18 | vue.$data.menuOpen = false; 19 | }, 20 | buttonCommand: (e) => { 21 | ocw.Command(($(e.target).closest('.button').attr('id'))).writeCommand(); 22 | }, 23 | actionCommand: (e) => { 24 | ocw.Command(($(e.target).closest('.action').attr('id'))).writeCommand(); 25 | }, 26 | lazyUpdate: true, 27 | lazyUpdateChange: () => { 28 | m.forEach((item) => vue.$data['b' + item.getIndex()].lazy = vue.$data.lazyUpdate); 29 | }, 30 | autoUpdate: false, 31 | autoUpdateRate: (rate) => { 32 | setTimeout(() => { 33 | if (vue.$data.autoUpdate) { 34 | j.readStatus().done((status) => { 35 | status.forEach((value, index) => { 36 | m[index].setValue(value); 37 | vue.$refs['m' + index][0].setValue(value); 38 | }); 39 | vue.$data.autoUpdateRate(rate); 40 | }); 41 | } else { 42 | vue.$data.autoUpdateRate(rate); 43 | } 44 | }, rate); 45 | }, 46 | command: '', 47 | commandWrite: () => { 48 | if (vue.$data.command) { 49 | ocw.Command(vue.$data.command).writeCommand(); 50 | } 51 | }, 52 | buttons: [ 53 | { 54 | name: 'Rest', 55 | command: 'krest' 56 | }, 57 | { 58 | name: 'Sit', 59 | command: 'ksit' 60 | }, 61 | { 62 | name: 'Stand', 63 | command: 'kbalance' 64 | }, 65 | { 66 | name: 'Butt', 67 | command: 'kbuttUp' 68 | }, 69 | { 70 | name: 'Pee', 71 | command: 'kpee' 72 | }, 73 | { 74 | name: 'Stretch', 75 | command: 'kstr' 76 | } 77 | ], 78 | sliders: [ 79 | { 80 | id: 0, 81 | name: 'hPan', 82 | direction: 'rtl', 83 | min: -60, 84 | max: 60 85 | }, 86 | { 87 | id: 1, 88 | name: 'hTilt', 89 | direction: 'rtl', 90 | min: -80, 91 | max: 50 92 | }, 93 | { 94 | id: 2, 95 | name: 'tPan', 96 | direction: 'rtl', 97 | min: -60, 98 | max: 60 99 | }, 100 | { 101 | id: 3, 102 | name: 'N/A', 103 | direction: 'rtl', 104 | min: -60, 105 | max: 60 106 | }, 107 | { 108 | id: 4, 109 | name: 'rFL', 110 | direction: 'rtl', 111 | min: -60, 112 | max: 60 113 | }, 114 | { 115 | id: 5, 116 | name: 'rFR', 117 | direction: 'rtl', 118 | min: -60, 119 | max: 60 120 | }, 121 | { 122 | id: 6, 123 | name: 'rHR', 124 | direction: 'rtl', 125 | min: -60, 126 | max: 60 127 | }, 128 | { 129 | id: 7, 130 | name: 'rHL', 131 | direction: 'rtl', 132 | min: -60, 133 | max: 60 134 | }, 135 | { 136 | id: 8, 137 | name: 'sFL', 138 | direction: 'rtl', 139 | min: -60, 140 | max: 90 141 | }, 142 | { 143 | id: 9, 144 | name: 'sFR', 145 | direction: 'rtl', 146 | min: -60, 147 | max: 90 148 | }, 149 | { 150 | id: 10, 151 | name: 'sHR', 152 | direction: 'rtl', 153 | min: -90, 154 | max: 60 155 | }, 156 | { 157 | id: 11, 158 | name: 'sHL', 159 | direction: 'rtl', 160 | min: -90, 161 | max: 60 162 | }, 163 | { 164 | id: 12, 165 | name: 'kFL', 166 | direction: 'rtl', 167 | min: -60, 168 | max: 60 169 | }, 170 | { 171 | id: 13, 172 | name: 'kFR', 173 | direction: 'rtl', 174 | min: -60, 175 | max: 60 176 | }, 177 | { 178 | id: 14, 179 | name: 'kHR', 180 | direction: 'rtl', 181 | min: -60, 182 | max: 60 183 | }, 184 | { 185 | id: 15, 186 | name: 'kHL', 187 | direction: 'rtl', 188 | min: -60, 189 | max: 60 190 | } 191 | ], 192 | change: (index) => { 193 | let value = vue.$data['m' + index]; 194 | if (value != m[index].getValue()) { 195 | let min = vue.$data['b' + index].min; 196 | let max = vue.$data['b' + index].max; 197 | m[index].writeValue(Math.max(min, Math.min(value, max))); 198 | m.forEach((item) => { 199 | let sync = vue.$data['b' + index].sync && vue.$data['b' + item.getIndex()].sync; 200 | if (index != item.getIndex() && sync) { 201 | let min = vue.$data['b' + item.getIndex()].min; 202 | let max = vue.$data['b' + item.getIndex()].max; 203 | vue.$refs['m' + item.getIndex()][0].setValue(Math.max(min, Math.min(value, max))); 204 | } 205 | }); 206 | } 207 | }, 208 | dragstart: () => { 209 | $(vue.$refs.autoUpdate).data('checked', vue.$data.autoUpdate); 210 | vue.$set(vue.$refs.autoUpdate, 'checked', false); 211 | }, 212 | dragend: () => { 213 | vue.$set(vue.$refs.autoUpdate, 'checked', $(vue.$refs.autoUpdate).data('checked')); 214 | } 215 | }; 216 | 217 | m.forEach((item) => { 218 | let slider = data.sliders.filter(s => s.id == item.getIndex())[0]; 219 | data['m' + item.getIndex()] = item.getValue(); 220 | data['b' + item.getIndex()] = $.extend(slider, { 221 | dotSize: 20, 222 | tooltip: 'always', 223 | tooltipPlacement: 'top', 224 | interval: 1, 225 | duration: 0, 226 | lazy: true, 227 | contained: false, 228 | useKeyboard: true, 229 | sync: false 230 | }, 231 | { 232 | sid: 's' + item.getIndex(), 233 | mid: 'm' + item.getIndex(), 234 | bid: 'b' + item.getIndex(), 235 | style: 'slider ' + slider.direction + ' ' + ([3, 4, 5, 6, 7].includes(slider.id) ? 'inactive' : 'active'), 236 | width: ['ltr', 'rtl'].includes(slider.direction) ? 300 : 5, 237 | height: ['ttb', 'btt'].includes(slider.direction) ? 300 : 5, 238 | process: (p) => [[(Math.abs(slider.min) * 100 / (Math.abs(slider.min) + Math.abs(slider.max))), p[0]]] 239 | }); 240 | }); 241 | 242 | return data; 243 | }, 244 | components: { 245 | 'vueSlider': window['vue-slider-component'], 246 | } 247 | }); 248 | 249 | vue.$data.autoUpdateRate(1000); 250 | 251 | let joystick = { 252 | size: 80, 253 | mode: 'static', 254 | position: { 255 | left: '50%', 256 | top: '50%' 257 | } 258 | }; 259 | 260 | let c = ocw.Command(); 261 | nipplejs.create($.extend(joystick, { 262 | zone: $('#left')[0], 263 | color: '#007acc' 264 | })).on('move, end', (e, data) => { 265 | let cActive = c.getCommand(); 266 | let direction = data.direction ? data.direction.y + '|' + data.direction.angle : 'stop'; 267 | switch (direction) { 268 | case 'up|up': 269 | c.setCommand('ktr'); 270 | break; 271 | case 'up|left': 272 | c.setCommand('kwkL'); 273 | break; 274 | case 'up|right': 275 | c.setCommand('kwkR'); 276 | break; 277 | case 'down|down': 278 | c.setCommand('kbk'); 279 | break; 280 | case 'down|left': 281 | c.setCommand('kbkL'); 282 | break; 283 | case 'down|right': 284 | c.setCommand('kbkR'); 285 | break; 286 | default: 287 | c.setCommand('kbalance'); 288 | break; 289 | } 290 | if (c.getCommand() != cActive) { 291 | c.writeCommand(); 292 | } 293 | }); 294 | 295 | let i = ocw.move.I(0, m[0].getValue(), 1, m[1].getValue()); 296 | nipplejs.create($.extend(joystick, { 297 | zone: $('#right')[0], 298 | color: '#f0b400' 299 | })).on('move, end', (e, data) => { 300 | let iActive = i.getIndexValue(); 301 | let direction = data.direction ? data.direction.y + '|' + data.direction.angle : 'stop'; 302 | let force = data.force ? data.force / 2 : 0; 303 | let left = Math.min(vue.$data['b0'].max, vue.$data['b0'].max * force); 304 | let right = Math.max(vue.$data['b0'].min, vue.$data['b0'].min * force); 305 | let up = Math.min(vue.$data['b1'].max, vue.$data['b1'].max * force); 306 | let down = Math.max(vue.$data['b1'].min, vue.$data['b1'].min * force); 307 | switch (direction) { 308 | case 'up|up': 309 | i.setIndexValue(0, iActive[1], 1, up); 310 | break; 311 | case 'up|left': 312 | i.setIndexValue(0, left, 1, iActive[0]); 313 | break; 314 | case 'up|right': 315 | i.setIndexValue(0, right, 1, iActive[0]); 316 | break; 317 | case 'down|down': 318 | i.setIndexValue(0, iActive[1], 1, down); 319 | break; 320 | case 'down|left': 321 | i.setIndexValue(0, left, 1, iActive[0]); 322 | break; 323 | case 'down|right': 324 | i.setIndexValue(0, right, 1, iActive[0]); 325 | break; 326 | default: 327 | i.setIndexValue(0, 0, 1, 0); 328 | break; 329 | } 330 | if (JSON.stringify(i.getIndexValue()) != JSON.stringify(iActive)) { 331 | i.writeIndexValue(); 332 | } 333 | }); 334 | }); 335 | -------------------------------------------------------------------------------- /web/js/vue.slider.min.js: -------------------------------------------------------------------------------- 1 | (function(t,e){"object"===typeof exports&&"object"===typeof module?module.exports=e(require("vue")):"function"===typeof define&&define.amd?define([],e):"object"===typeof exports?exports["vue-slider-component"]=e(require("vue")):t["vue-slider-component"]=e(t["Vue"])})("undefined"!==typeof self?self:this,function(t){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"===typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t["default"]}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s="fb15")}({2350:function(t,e){function r(t,e){var r=t[1]||"",o=t[3];if(!o)return r;if(e&&"function"===typeof btoa){var i=n(o),s=o.sources.map(function(t){return"/*# sourceURL="+o.sourceRoot+t+" */"});return[r].concat(s).concat([i]).join("\n")}return[r].join("\n")}function n(t){var e=btoa(unescape(encodeURIComponent(JSON.stringify(t)))),r="sourceMappingURL=data:application/json;charset=utf-8;base64,"+e;return"/*# "+r+" */"}t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var n=r(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n}).join("")},e.i=function(t,r){"string"===typeof t&&(t=[[null,t,""]]);for(var n={},o=0;or.parts.length&&(n.parts.length=r.parts.length)}else{var s=[];for(o=0;o-1)e[t]=r[t];else{var n=Object.getOwnPropertyDescriptor(r,t);void 0!==n.value?"function"===typeof n.value?(e.methods||(e.methods={}))[t]=n.value:(e.mixins||(e.mixins=[])).push({data:function(){var e;return e={},e[t]=n.value,e}}):(n.get||n.set)&&((e.computed||(e.computed={}))[t]={get:n.get,set:n.set})}}),(e.mixins||(e.mixins=[])).push({data:function(){return p(this,t)}});var n=t.__decorators__;n&&(n.forEach(function(t){return t(e)}),delete t.__decorators__);var a=Object.getPrototypeOf(t.prototype),u=a instanceof o?a.constructor:o,l=u.extend(e);return v(l,t,u),i&&s(l,t),l}function v(t,e,r){Object.getOwnPropertyNames(e).forEach(function(n){if("prototype"!==n){var o=Object.getOwnPropertyDescriptor(t,n);if(!o||o.configurable){var i=Object.getOwnPropertyDescriptor(e,n);if(!l){if("cid"===n)return;var s=Object.getOwnPropertyDescriptor(r,n);if(!f(i.value)&&s&&s.value===i.value)return}0,Object.defineProperty(t,n,i)}}})}function m(t){return"function"===typeof t?y(t):function(e){return y(e,t)}}m.registerHooks=function(t){h.push.apply(h,t)},e.default=m,e.createDecorator=c,e.mixins=d},"8bbf":function(e,r){e.exports=t},ae61:function(t,e,r){e=t.exports=r("2350")(!1),e.push([t.i,".vue-slider-dot{position:absolute;will-change:transform;-webkit-transition:all 0s;transition:all 0s;z-index:5}.vue-slider-dot-tooltip{position:absolute;visibility:hidden}.vue-slider-dot-tooltip-show{visibility:visible}.vue-slider-dot-tooltip-top{top:-10px;left:50%;-webkit-transform:translate(-50%,-100%);transform:translate(-50%,-100%)}.vue-slider-dot-tooltip-bottom{bottom:-10px;left:50%;-webkit-transform:translate(-50%,100%);transform:translate(-50%,100%)}.vue-slider-dot-tooltip-left{left:-10px;top:50%;-webkit-transform:translate(-100%,-50%);transform:translate(-100%,-50%)}.vue-slider-dot-tooltip-right{right:-10px;top:50%;-webkit-transform:translate(100%,-50%);transform:translate(100%,-50%)}",""])},d5ac:function(t,e,r){e=t.exports=r("2350")(!1),e.push([t.i,".vue-slider-marks{position:relative;width:100%;height:100%}.vue-slider-mark{position:absolute;z-index:1}.vue-slider-ltr .vue-slider-mark,.vue-slider-rtl .vue-slider-mark{width:0;height:100%;top:50%}.vue-slider-ltr .vue-slider-mark-step,.vue-slider-rtl .vue-slider-mark-step{top:0}.vue-slider-ltr .vue-slider-mark-label,.vue-slider-rtl .vue-slider-mark-label{top:100%;margin-top:10px}.vue-slider-ltr .vue-slider-mark{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.vue-slider-ltr .vue-slider-mark-step{left:0}.vue-slider-ltr .vue-slider-mark-label{left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.vue-slider-rtl .vue-slider-mark{-webkit-transform:translate(50%,-50%);transform:translate(50%,-50%)}.vue-slider-rtl .vue-slider-mark-step{right:0}.vue-slider-rtl .vue-slider-mark-label{right:50%;-webkit-transform:translateX(50%);transform:translateX(50%)}.vue-slider-btt .vue-slider-mark,.vue-slider-ttb .vue-slider-mark{width:100%;height:0;left:50%}.vue-slider-btt .vue-slider-mark-step,.vue-slider-ttb .vue-slider-mark-step{left:0}.vue-slider-btt .vue-slider-mark-label,.vue-slider-ttb .vue-slider-mark-label{left:100%;margin-left:10px}.vue-slider-btt .vue-slider-mark{-webkit-transform:translate(-50%,50%);transform:translate(-50%,50%)}.vue-slider-btt .vue-slider-mark-step{top:0}.vue-slider-btt .vue-slider-mark-label{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.vue-slider-ttb .vue-slider-mark{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.vue-slider-ttb .vue-slider-mark-step{bottom:0}.vue-slider-ttb .vue-slider-mark-label{bottom:50%;-webkit-transform:translateY(50%);transform:translateY(50%)}.vue-slider-mark-label,.vue-slider-mark-step{position:absolute}",""])},df80:function(t,e,r){e=t.exports=r("2350")(!1),e.push([t.i,".vue-slider{position:relative;-webkit-box-sizing:content-box;box-sizing:content-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:block;-ms-touch-action:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.vue-slider-disabled{pointer-events:none}.vue-slider-rail{position:relative;width:100%;height:100%;-webkit-transition-property:width,height,left,right,top,bottom;transition-property:width,height,left,right,top,bottom}.vue-slider-process{position:absolute;z-index:1}.vue-slider-sr-only{clip:rect(1px,1px,1px,1px);height:1px;width:1px;overflow:hidden;position:absolute!important}",""])},fb15:function(t,e,r){"use strict";var n;(r.r(e),"undefined"!==typeof window)&&((n=window.document.currentScript)&&(n=n.src.match(/(.+\/)[^\/]+\.js(\?.*)?$/))&&(r.p=n[1]));function o(t,e,r,n){var o,i=arguments.length,s=i<3?e:null===n?n=Object.getOwnPropertyDescriptor(e,r):n;if("object"===typeof Reflect&&"function"===typeof Reflect.decorate)s=Reflect.decorate(t,e,r,n);else for(var a=t.length-1;a>=0;a--)(o=t[a])&&(s=(i<3?o(s):i>3?o(e,r,s):o(e,r))||s);return i>3&&s&&Object.defineProperty(e,r,s),s}var i=r("8bbf"),s=r.n(i),a=r("65d9"),u=r.n(a);var l="undefined"!==typeof Reflect&&"undefined"!==typeof Reflect.getMetadata;function c(t,e,r){l&&(Array.isArray(t)||"function"===typeof t||"undefined"!==typeof t.type||(t.type=Reflect.getMetadata("design:type",e,r)))}function d(t,e){return void 0===e&&(e={}),function(r,n){c(e,r,n),Object(a["createDecorator"])(function(r,n){(r.props||(r.props={}))[n]=e,r.model={prop:n,event:t||n}})(r,n)}}function f(t){return void 0===t&&(t={}),function(e,r){c(t,e,r),Object(a["createDecorator"])(function(e,r){(e.props||(e.props={}))[r]=t})(e,r)}}function p(t,e){void 0===e&&(e={});var r=e.deep,n=void 0!==r&&r,o=e.immediate,i=void 0!==o&&o;return Object(a["createDecorator"])(function(e,r){"object"!==typeof e.watch&&(e.watch=Object.create(null));var o=e.watch;"object"!==typeof o[t]||Array.isArray(o[t])?"undefined"===typeof o[t]&&(o[t]=[]):o[t]=[o[t]],o[t].push({handler:r,deep:n,immediate:i})})}r("4ed8");function h(t){return h="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},h(t)}function y(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function v(t,e){for(var r=0;r-1},required:!0})],O.prototype,"tooltipPlacement",void 0),o([f({type:[String,Function]})],O.prototype,"tooltipFormatter",void 0),o([f({type:Boolean,default:!1})],O.prototype,"focus",void 0),o([f({default:!1})],O.prototype,"disabled",void 0),O=o([u.a],O);var P=O;r("556c");function S(t){return S="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},S(t)}function E(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function R(t,e){for(var r=0;rthis.total&&(t=this.total),this.data?this.data[t]:new G(t).multiply(this.interval).plus(this.min).toNumber()}},{key:"setDotPos",value:function(t,e){t=this.getValidPos(t,e).pos;var r=t-this.dotsPos[e];if(r){var n=new Array(this.dotsPos.length);this.fixed?n=this.getFixedChangePosArr(r,e):this.minRange||this.maxRange?n=this.getLimitRangeChangePosArr(t,r,e):n[e]=r,this.setDotsPos(this.dotsPos.map(function(t,e){return t+(n[e]||0)}))}}},{key:"getFixedChangePosArr",value:function(t,e){var r=this;return this.dotsPos.forEach(function(n,o){if(o!==e){var i=r.getValidPos(n+t,o),s=i.pos,a=i.inRange;a||(t=Math.min(Math.abs(s-n),Math.abs(t))*(t<0?-1:1))}}),this.dotsPos.map(function(e){return t})}},{key:"getLimitRangeChangePosArr",value:function(t,e,r){var n=this,o=[{index:r,changePos:e}],i=e;return[this.minRange,this.maxRange].forEach(function(s,a){if(!s)return!1;var u=0===a,l=e>0,c=0;c=u?l?1:-1:l?-1:1;var d=function(t,e){var r=Math.abs(t-e);return u?rn.maxRangeDir},f=r+c,p=n.dotsPos[f],h=t;while(n.isPos(p)&&d(p,h)){var y=n.getValidPos(p+i,f),v=y.pos;o.push({index:f,changePos:v-p}),f+=c,h=v,p=n.dotsPos[f]}}),this.dotsPos.map(function(t,e){var r=o.filter(function(t){return t.index===e});return r.length?r[0].changePos:0})}},{key:"isPos",value:function(t){return"number"===typeof t}},{key:"getValidPos",value:function(t,e){var r=this.valuePosRange[e],n=!0;return tr[1]&&(t=r[1],n=!1),{pos:t,inRange:n}}},{key:"parseValue",value:function(t){if(this.data)t=this.data.indexOf(t);else if("number"===typeof t||"string"===typeof t){if(t=+t,tthis.max)return this.emitError(W.MAX),0;if("number"!==typeof t||t!==t)return this.emitError(W.VALUE),0;t=new G(t).minus(this.min).divide(this.interval).toNumber()}var e=new G(t).multiply(this.gap).toNumber();return e<0?0:e>100?100:e}},{key:"parsePos",value:function(t){var e=Math.round(t/this.gap);return this.getValueByIndex(e)}},{key:"isActiveByPos",value:function(t){return this.processArray.some(function(e){var r=K(e,2),n=r[0],o=r[1];return t>=n&&t<=o})}},{key:"getValues",value:function(){if(this.data)return this.data;for(var t=[],e=0;e<=this.total;e++)t.push(new G(e).multiply(this.interval).plus(this.min).toNumber());return t}},{key:"emitError",value:function(t){this.onError&&this.onError(t,st[t])}},{key:"getDotRange",value:function(t,e,r){if(!this.dotOptions)return r;var n=Array.isArray(this.dotOptions)?this.dotOptions[t]:this.dotOptions;return n&&void 0!==n[e]?this.parseValue(n[e]):r}},{key:"markList",get:function(){var t=this;if(!this.marks)return[];var e=function(e,r){var n=t.parseValue(e);return X({pos:n,value:e,label:e,active:t.isActiveByPos(n)},r)};return!0===this.marks?this.getValues().map(function(t){return e(t)}):"[object Object]"===Object.prototype.toString.call(this.marks)?Object.keys(this.marks).sort(function(t,e){return+t-+e}).map(function(r){var n=t.marks[r];return e(r,"string"!==typeof n?n:{label:n})}):Array.isArray(this.marks)?this.marks.map(function(t){return e(t)}):"function"===typeof this.marks?this.getValues().map(function(e){return{value:e,result:t.marks(e)}}).filter(function(t){var e=t.result;return!!e}).map(function(t){var r=t.value,n=t.result;return e(r,n)}):[]}},{key:"processArray",get:function(){if(this.process){if("function"===typeof this.process)return this.process(this.dotsPos);if(1===this.dotsPos.length)return[[0,this.dotsPos[0]]];if(this.dotsPos.length>1)return[[Math.min.apply(Math,Q(this.dotsPos)),Math.max.apply(Math,Q(this.dotsPos))]]}return[]}},{key:"total",get:function(){var t=0;return t=this.data?this.data.length-1:new G(this.max).minus(this.min).divide(this.interval).toNumber(),t-Math.floor(t)!==0?(this.emitError(W.INTERVAL),0):t}},{key:"gap",get:function(){return 100/this.total}},{key:"minRangeDir",get:function(){return this.minRange?this.minRange*this.gap:0}},{key:"maxRangeDir",get:function(){return this.maxRange?this.maxRange*this.gap:100}},{key:"valuePosRange",get:function(){var t=this,e=this.dotsPos,r=[];return e.forEach(function(n,o){r.push([Math.max(t.minRange?t.minRangeDir*o:0,t.enableCross?0:e[o-1]||0,t.getDotRange(o,"min",0)),Math.min(t.minRange?100-t.minRangeDir*(e.length-1-o):100,t.enableCross?100:e[o+1]||100,t.getDotRange(o,"max",100))])}),r}},{key:"dotsIndex",get:function(){var t=this;return this.dotsValue.map(function(e){return t.getIndexByValue(e)})}}]),t}();function ut(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function lt(t,e){for(var r=0;r-1&&t.control.syncDotsPos()})})}},{key:"isDisabledByDotIndex",value:function(t){return this.dots[t].disabled}},{key:"syncValueByPos",value:function(){var t=this.control.dotsValue;this.isDiff(t,Array.isArray(this.value)?this.value:[this.value])&&this.$emit("change",1===t.length?t[0]:gt(t))}},{key:"isDiff",value:function(t,e){return t.length!==e.length||t.some(function(t,r){return t!==e[r]})}},{key:"emitError",value:function(t,e){this.silent||console.error("[VueSlider error]: ".concat(e)),this.$emit("error",t,e)}},{key:"dragStart",value:function(t){this.focusDotIndex=t,this.setScale(),this.states.add(Vt.Drag),this.states.add(Vt.Focus),this.$emit("drag-start")}},{key:"dragMove",value:function(t){if(!this.states.has(Vt.Drag))return!1;t.preventDefault();var e=this.getPosByEvent(t);this.isCrossDot(e),this.control.setDotPos(e,this.focusDotIndex),this.lazy||this.syncValueByPos();var r=this.control.dotsValue;this.$emit("dragging",1===r.length?r[0]:gt(r))}},{key:"isCrossDot",value:function(t){if(this.canSort){var e=this.focusDotIndex,r=t;r>this.dragRange[1]?(r=this.dragRange[1],this.focusDotIndex++):r0&&void 0!==arguments[0]?arguments[0]:0;this.states.add(Vt.Focus),this.focusDotIndex=t}},{key:"blur",value:function(){this.states.delete(Vt.Focus)}},{key:"getValue",value:function(){var t=this.control.dotsValue;return 1===t.length?t[0]:t}},{key:"getIndex",value:function(){var t=this.control.dotsIndex;return 1===t.length?t[0]:t}},{key:"setValue",value:function(t){this.control.setValue(Array.isArray(t)?gt(t):[t]),this.syncValueByPos()}},{key:"setIndex",value:function(t){var e=this,r=Array.isArray(t)?t.map(function(t){return e.control.getValueByIndex(t)}):this.control.getValueByIndex(t);this.setValue(r)}},{key:"setValueByPos",value:function(t){var e=this,r=this.control.getRecentDot(t);if(this.isDisabledByDotIndex(r))return!1;this.focusDotIndex=r,this.control.setDotPos(t,r),this.syncValueByPos(),this.useKeyboard&&this.states.add(Vt.Focus),setTimeout(function(){e.included&&e.isNotSync?e.control.setValue(e.value):e.control.syncDotsPos()})}},{key:"keydownHandle",value:function(t){if(!this.useKeyboard||!this.states.has(Vt.Focus))return!1;var e=H(t,{direction:this.direction,max:this.control.total,min:0,hook:this.keydownHook});if(e){t.preventDefault();var r=this.control.getIndexByValue(this.control.dotsValue[this.focusDotIndex]),n=e(r),o=this.control.parseValue(this.control.getValueByIndex(n));this.isCrossDot(o),this.control.setDotPos(o,this.focusDotIndex),this.syncValueByPos()}}},{key:"getPosByEvent",value:function(t){return L(t,this.$el,this.isReverse)[this.isHorizontal?"x":"y"]/this.scale}},{key:"renderSlot",value:function(t,e,r,n){var o=this.$createElement,i=this.$scopedSlots[t];return i?n?i(e):o("template",{slot:t},[i(e)]):r}},{key:"render",value:function(){var t=this,e=arguments[0];return e("div",{ref:"container",class:this.containerClasses,style:this.containerStyles,attrs:{"aria-hidden":!0},on:{click:this.clickHandle}},[e("div",{class:"vue-slider-rail",style:this.railStyle},[this.processArray.map(function(r,n){return t.renderSlot("process",r,e("div",{class:"vue-slider-process",key:"process-".concat(n),style:r.style}),!0)}),this.marks?e("div",{class:"vue-slider-marks"},[this.control.markList.map(function(r,n){var o;return t.renderSlot("mark",r,e("vue-slider-mark",{key:"mark-".concat(n),attrs:{mark:r,hideLabel:t.hideLabel,stepStyle:t.stepStyle,stepActiveStyle:t.stepActiveStyle,labelStyle:t.labelStyle,labelActiveStyle:t.labelActiveStyle},style:(o={},bt(o,t.isHorizontal?"height":"width","100%"),bt(o,t.isHorizontal?"width":"height",t.tailSize),bt(o,t.mainDirection,"".concat(r.pos,"%")),o),on:{pressLabel:function(e){return t.setValueByPos(e)}}},[t.renderSlot("step",r,null),t.renderSlot("label",r,null)]),!0)})]):null,this.dots.map(function(r,n){var o;return e("vue-slider-dot",{ref:"dot-".concat(n),key:"dot-".concat(n),attrs:{value:r.value,disabled:r.disabled,focus:r.focus,"dot-style":[r.style,r.disabled?r.disabledStyle:null,r.focus?r.focusStyle:null],tooltip:r.tooltip||t.tooltip,"tooltip-style":[t.tooltipStyle,r.tooltipStyle,r.disabled?r.tooltipDisabledStyle:null,r.focus?r.tooltipFocusStyle:null],"tooltip-formatter":Array.isArray(t.tooltipFormatter)?t.tooltipFormatter[n]:t.tooltipFormatter,"tooltip-placement":t.tooltipDirections[n]},style:[t.dotBaseStyle,(o={},bt(o,t.mainDirection,"".concat(r.pos,"%")),bt(o,"transition","".concat(t.mainDirection," ").concat(t.animateTime,"s")),o)],on:{"drag-start":function(){return t.dragStart(n)}}},[t.renderSlot("dot",r,null),t.renderSlot("tooltip",r,null)])})]),1!==this.dots.length||this.data?null:e("input",{class:"vue-slider-sr-only",attrs:{type:"range",min:this.min,max:this.max},domProps:{value:this.value}})])}},{key:"tailSize",get:function(){return B((this.isHorizontal?this.height:this.width)||_t)}},{key:"containerClasses",get:function(){return["vue-slider",["vue-slider-".concat(this.direction)],{"vue-slider-disabled":this.disabled}]}},{key:"containerStyles",get:function(){var t=Array.isArray(this.dotSize)?this.dotSize:[this.dotSize,this.dotSize],e=ht(t,2),r=e[0],n=e[1],o=this.width?B(this.width):this.isHorizontal?"auto":B(_t),i=this.height?B(this.height):this.isHorizontal?B(_t):"auto";return{padding:this.contained?"".concat(n/2,"px ").concat(r/2,"px"):this.isHorizontal?"".concat(n/2,"px 0"):"0 ".concat(r/2,"px"),width:o,height:i}}},{key:"processArray",get:function(){var t=this;return this.control.processArray.map(function(e){var r,n=ht(e,3),o=n[0],i=n[1],s=n[2];if(o>i){var a=[i,o];o=a[0],i=a[1]}var u=t.isHorizontal?"width":"height";return{start:o,end:i,style:pt((r={},bt(r,t.isHorizontal?"height":"width","100%"),bt(r,t.isHorizontal?"top":"left",0),bt(r,t.mainDirection,"".concat(o,"%")),bt(r,u,"".concat(i-o,"%")),bt(r,"transitionProperty","".concat(u,",").concat(t.mainDirection)),bt(r,"transitionDuration","".concat(t.animateTime,"s")),r),t.processStyle,s)}})}},{key:"dotBaseStyle",get:function(){var t,e=Array.isArray(this.dotSize)?this.dotSize:[this.dotSize,this.dotSize],r=ht(e,2),n=r[0],o=r[1];return t=this.isHorizontal?bt({transform:"translate(".concat(this.isReverse?"50%":"-50%",", -50%)"),WebkitTransform:"translate(".concat(this.isReverse?"50%":"-50%",", -50%)"),top:"50%"},"ltr"===this.direction?"left":"right","0"):bt({transform:"translate(-50%, ".concat(this.isReverse?"50%":"-50%",")"),WebkitTransform:"translate(-50%, ".concat(this.isReverse?"50%":"-50%",")"),left:"50%"},"btt"===this.direction?"bottom":"top","0"),pt({width:"".concat(n,"px"),height:"".concat(o,"px")},t)}},{key:"mainDirection",get:function(){switch(this.direction){case"ltr":return"left";case"rtl":return"right";case"btt":return"bottom";case"ttb":return"top"}}},{key:"isHorizontal",get:function(){return"ltr"===this.direction||"rtl"===this.direction}},{key:"isReverse",get:function(){return"rtl"===this.direction||"btt"===this.direction}},{key:"tooltipDirections",get:function(){var t=this.tooltipPlacement||(this.isHorizontal?"top":"left");return Array.isArray(t)?t:this.dots.map(function(){return t})}},{key:"dots",get:function(){var t=this;return this.control.dotsPos.map(function(e,r){return pt({pos:e,index:r,value:t.control.dotsValue[r],focus:t.states.has(Vt.Focus)&&t.focusDotIndex===r,disabled:!1,style:t.dotStyle},(Array.isArray(t.dotOptions)?t.dotOptions[r]:t.dotOptions)||{})})}},{key:"animateTime",get:function(){return this.states.has(Vt.Drag)?0:this.duration}},{key:"canSort",get:function(){return this.order&&!this.minRange&&!this.maxRange&&!this.fixed&&this.enableCross}},{key:"isNotSync",get:function(){var t=this.control.dotsValue;return Array.isArray(this.value)?this.value.length!==t.length||this.value.some(function(e,r){return e!==t[r]}):this.value!==t[0]}},{key:"dragRange",get:function(){var t=this.dots[this.focusDotIndex-1],e=this.dots[this.focusDotIndex+1];return[t?t.pos:-1/0,e?e.pos:1/0]}}]),e}(s.a);o([d("change",{default:0})],Mt.prototype,"value",void 0),o([f({type:Boolean,default:!1})],Mt.prototype,"silent",void 0),o([f({default:"ltr",validator:function(t){return["ltr","rtl","ttb","btt"].indexOf(t)>-1}})],Mt.prototype,"direction",void 0),o([f({type:[Number,String]})],Mt.prototype,"width",void 0),o([f({type:[Number,String]})],Mt.prototype,"height",void 0),o([f({default:14})],Mt.prototype,"dotSize",void 0),o([f({default:!1})],Mt.prototype,"contained",void 0),o([f({type:Number,default:0})],Mt.prototype,"min",void 0),o([f({type:Number,default:100})],Mt.prototype,"max",void 0),o([f({type:Number,default:1})],Mt.prototype,"interval",void 0),o([f({type:Boolean,default:!1})],Mt.prototype,"disabled",void 0),o([f({type:Boolean,default:!0})],Mt.prototype,"clickable",void 0),o([f({type:Number,default:.5})],Mt.prototype,"duration",void 0),o([f(Array)],Mt.prototype,"data",void 0),o([f({type:Boolean,default:!1})],Mt.prototype,"lazy",void 0),o([f({type:String,validator:function(t){return["none","always","focus"].indexOf(t)>-1},default:"focus"})],Mt.prototype,"tooltip",void 0),o([f({type:[String,Array],validator:function(t){return(Array.isArray(t)?t:[t]).every(function(t){return["top","right","bottom","left"].indexOf(t)>-1})}})],Mt.prototype,"tooltipPlacement",void 0),o([f({type:[String,Array,Function]})],Mt.prototype,"tooltipFormatter",void 0),o([f({type:Boolean,default:!1})],Mt.prototype,"useKeyboard",void 0),o([f({type:Function,default:function(){return!1}})],Mt.prototype,"keydownHook",void 0),o([f({type:Boolean,default:!0})],Mt.prototype,"enableCross",void 0),o([f({type:Boolean,default:!1})],Mt.prototype,"fixed",void 0),o([f({type:Boolean,default:!0})],Mt.prototype,"order",void 0),o([f(Number)],Mt.prototype,"minRange",void 0),o([f(Number)],Mt.prototype,"maxRange",void 0),o([f({type:[Boolean,Object,Array,Function],default:!1})],Mt.prototype,"marks",void 0),o([f({type:[Boolean,Function],default:!0})],Mt.prototype,"process",void 0),o([f(Boolean)],Mt.prototype,"included",void 0),o([f(Boolean)],Mt.prototype,"adsorb",void 0),o([f(Boolean)],Mt.prototype,"hideLabel",void 0),o([f()],Mt.prototype,"dotOptions",void 0),o([f()],Mt.prototype,"railStyle",void 0),o([f()],Mt.prototype,"processStyle",void 0),o([f()],Mt.prototype,"dotStyle",void 0),o([f()],Mt.prototype,"tooltipStyle",void 0),o([f()],Mt.prototype,"stepStyle",void 0),o([f()],Mt.prototype,"stepActiveStyle",void 0),o([f()],Mt.prototype,"labelStyle",void 0),o([f()],Mt.prototype,"labelActiveStyle",void 0),o([p("value")],Mt.prototype,"onValueChanged",null),Mt=o([u()({data:function(){return{control:null}},components:{VueSliderDot:P,VueSliderMark:T},inheritAttrs:!1})],Mt);var Ct=Mt,Nt=Ct;r.d(e,"ERROR_TYPE",function(){return W});e["default"]=Nt}})["default"]}); 7 | //# sourceMappingURL=vue-slider-component.umd.min.js.map 8 | -------------------------------------------------------------------------------- /web/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OpenCatWeb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 32 | 51 | 82 | 85 |
86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | --------------------------------------------------------------------------------