Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f0b6f2d26 | ||
|
|
5846d46e0c | ||
|
|
1454987fcf | ||
|
|
2ba04b92d7 | ||
|
|
6a7493a7be | ||
|
|
565b2113a5 | ||
|
|
128515a9a7 | ||
|
|
038c3b6466 | ||
|
|
fa5953a231 | ||
|
|
356c4557bb | ||
|
|
5ff9d17850 | ||
|
|
ccbb1886af | ||
|
|
65d177f149 | ||
|
|
7cf82753ff | ||
|
|
c4d399ccb0 | ||
|
|
521bc63c22 | ||
|
|
b02aebf8c2 | ||
|
|
4c2421121f | ||
|
|
6e1173cfcf | ||
|
|
1742f4604a | ||
|
|
10fafd7c23 | ||
|
|
c838883e69 | ||
|
|
384372e6c8 | ||
|
|
74c7628474 | ||
|
|
bd43c4d9c3 | ||
|
|
2e004b6048 | ||
|
|
ab921d2523 | ||
|
|
9ac5143228 | ||
|
|
2bea6397c6 | ||
|
|
ea97752867 | ||
|
|
a12dcfc86f | ||
|
|
b89db56c48 | ||
|
|
6b603a1a8c | ||
|
|
0caadb6f41
|
||
|
|
ff5aa4c12c | ||
|
|
0967d7f94a | ||
|
|
26e385b4c0
|
||
|
|
5cc3003e47
|
||
|
|
3e6187dba9
|
||
|
|
7407419e56
|
||
|
|
93824964ed | ||
|
|
abecf0d4ce | ||
|
|
d6d985a172 | ||
|
|
71cab02b3e | ||
|
|
3926776adc | ||
|
|
3b7cd0a42e | ||
|
|
f85bcb3ef6 | ||
|
|
0f9809c290 | ||
|
|
2d22d5cff1 | ||
|
|
ab2dc10e35 | ||
|
|
34b72625a5 | ||
|
|
a3567ec338 | ||
|
|
7576cd859a | ||
|
|
d82c33d774 | ||
|
|
d57ed19c42 | ||
|
|
bee99b4c55 | ||
|
|
fe44927a62 | ||
|
|
8f81616ca8 | ||
|
|
15f539f4d4 | ||
|
|
3b6dfbda49 | ||
|
|
dd08290587 | ||
|
|
b8ed46cbea | ||
|
|
8d7419b666 | ||
|
|
830ec073bf | ||
|
|
7d6cb2b660 | ||
|
|
1d6d6ee228 |
@@ -11,6 +11,7 @@ espfs/espfstest/espfstest
|
|||||||
html_compressed/
|
html_compressed/
|
||||||
ldscript_memspecific.ld
|
ldscript_memspecific.ld
|
||||||
eagle.app.sym
|
eagle.app.sym
|
||||||
|
node_modules
|
||||||
|
|
||||||
# Garbage added by CLion
|
# Garbage added by CLion
|
||||||
.idea/
|
.idea/
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
[submodule "libesphttpd"]
|
[submodule "libesphttpd"]
|
||||||
path = libesphttpd
|
path = libesphttpd
|
||||||
url = git@github.com:MightyPork/libesphttpd.git
|
url = git@github.com:MightyPork/libesphttpd.git
|
||||||
|
[submodule "front-end"]
|
||||||
|
path = front-end
|
||||||
|
url = git@github.com:espterm/espterm-front-end.git
|
||||||
|
branch = master
|
||||||
|
|||||||
+2
-3
@@ -110,8 +110,6 @@ set(SOURCE_FILES
|
|||||||
user/serial.h
|
user/serial.h
|
||||||
user/routes.c
|
user/routes.c
|
||||||
user/routes.h
|
user/routes.h
|
||||||
user/uart_asyncdrv.c-
|
|
||||||
user/uart_asyncdrv.h-
|
|
||||||
user/cgi_main.c
|
user/cgi_main.c
|
||||||
user/cgi_main.h
|
user/cgi_main.h
|
||||||
user/cgi_sockets.c
|
user/cgi_sockets.c
|
||||||
@@ -141,7 +139,7 @@ set(SOURCE_FILES
|
|||||||
user/apars_osc.c
|
user/apars_osc.c
|
||||||
user/apars_osc.h
|
user/apars_osc.h
|
||||||
user/apars_dcs.c
|
user/apars_dcs.c
|
||||||
user/apars_dcs.h user/uart_buffer.c user/uart_buffer.h user/jstring.c user/jstring.h user/character_sets.h)
|
user/apars_dcs.h user/uart_buffer.c user/uart_buffer.h user/jstring.c user/jstring.h user/character_sets.h user/utf8.h user/utf8.c user/cgi_logging.h)
|
||||||
|
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
include_directories(user)
|
include_directories(user)
|
||||||
@@ -155,6 +153,7 @@ include_directories(esp_iot_sdk_v1.5.2/include)
|
|||||||
add_definitions(
|
add_definitions(
|
||||||
-D__ets__
|
-D__ets__
|
||||||
-DICACHE_FLASH
|
-DICACHE_FLASH
|
||||||
|
-DUSE_OPTIMIZE_PRINTF=1
|
||||||
-DHTTPD_MAX_CONNECTIONS=5
|
-DHTTPD_MAX_CONNECTIONS=5
|
||||||
-DHTTPD_STACKSIZE=1000
|
-DHTTPD_STACKSIZE=1000
|
||||||
-DICACHE_FLASH_ATTR=
|
-DICACHE_FLASH_ATTR=
|
||||||
|
|||||||
@@ -62,12 +62,13 @@ LIBS = c gcc hal phy pp net80211 wpa main lwip crypto
|
|||||||
#Add in esphttpd lib
|
#Add in esphttpd lib
|
||||||
LIBS += esphttpd
|
LIBS += esphttpd
|
||||||
|
|
||||||
# compiler flags using during compilation of source files
|
# compiler flags using during compilation of source files -ggdb
|
||||||
CFLAGS = -Os -ggdb -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
|
CFLAGS = -Os -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
|
||||||
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \
|
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \
|
||||||
-Wno-address -Wno-unused
|
-Wno-address -Wno-unused
|
||||||
|
|
||||||
CFLAGS += -DGIT_HASH='"$(shell git rev-parse --short HEAD)"'
|
CFLAGS += -DGIT_HASH_BACKEND='"$(shell git rev-parse --short HEAD)"'
|
||||||
|
CFLAGS += -DGIT_HASH_FRONTEND='"$(shell cd front-end && git rev-parse --short HEAD)"'
|
||||||
CFLAGS += -DADMIN_PASSWORD=$(ADMIN_PASSWORD)
|
CFLAGS += -DADMIN_PASSWORD=$(ADMIN_PASSWORD)
|
||||||
|
|
||||||
ifdef GLOBAL_CFLAGS
|
ifdef GLOBAL_CFLAGS
|
||||||
@@ -152,7 +153,6 @@ define maplookup
|
|||||||
$(patsubst $(strip $(1)):%,%,$(filter $(strip $(1)):%,$(2)))
|
$(patsubst $(strip $(1)):%,%,$(filter $(strip $(1)):%,$(2)))
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
||||||
#Include options and target specific to the OUTPUT_TYPE
|
#Include options and target specific to the OUTPUT_TYPE
|
||||||
include Makefile.$(OUTPUT_TYPE)
|
include Makefile.$(OUTPUT_TYPE)
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ MODULE_INCDIR := $(addsuffix /include,$(INCDIR))
|
|||||||
ESP_FLASH_SIZE_IX=$(call maplookup,$(ESP_SPI_FLASH_SIZE_K),512:0 1024:2 2048:5 4096:6)
|
ESP_FLASH_SIZE_IX=$(call maplookup,$(ESP_SPI_FLASH_SIZE_K),512:0 1024:2 2048:5 4096:6)
|
||||||
ESPTOOL_FREQ=$(call maplookup,$(ESP_FLASH_FREQ_DIV),0:40m 1:26m 2:20m 0xf:80m 15:80m)
|
ESPTOOL_FREQ=$(call maplookup,$(ESP_FLASH_FREQ_DIV),0:40m 1:26m 2:20m 0xf:80m 15:80m)
|
||||||
ESPTOOL_MODE=$(call maplookup,$(ESP_FLASH_MODE),0:qio 1:qout 2:dio 3:dout)
|
ESPTOOL_MODE=$(call maplookup,$(ESP_FLASH_MODE),0:qio 1:qout 2:dio 3:dout)
|
||||||
ESPTOOL_SIZE=$(call maplookup,$(ESP_SPI_FLASH_SIZE_K),512:4m 256:2m 1024:8m 2048:16m 4096:32m)
|
ESPTOOL_SIZE=$(call maplookup,$(ESP_SPI_FLASH_SIZE_K),512:512KB 256:256KB 1024:1MB 2048:2MB 4096:4MB)
|
||||||
|
|
||||||
ESPTOOL_OPTS=--port $(ESPPORT) --baud $(ESPBAUD)
|
ESPTOOL_OPTS=--port $(ESPPORT) --baud $(ESPBAUD)
|
||||||
ESPTOOL_FLASHDEF=--flash_freq $(ESPTOOL_FREQ) --flash_mode $(ESPTOOL_MODE) --flash_size $(ESPTOOL_SIZE)
|
ESPTOOL_FLASHDEF=--flash_freq $(ESPTOOL_FREQ) --flash_mode $(ESPTOOL_MODE) --flash_size $(ESPTOOL_SIZE)
|
||||||
@@ -189,7 +189,7 @@ $1/%.o: %.S
|
|||||||
$(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@
|
$(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@
|
||||||
endef
|
endef
|
||||||
|
|
||||||
.PHONY: all web parser checkdirs clean libesphttpd default-tgt
|
.PHONY: all web parser checkdirs clean libesphttpd default-tgt espsize espmac
|
||||||
|
|
||||||
web:
|
web:
|
||||||
$(Q) ./build_web.sh
|
$(Q) ./build_web.sh
|
||||||
@@ -197,19 +197,31 @@ web:
|
|||||||
parser:
|
parser:
|
||||||
$(Q) ./build_parser.sh
|
$(Q) ./build_parser.sh
|
||||||
|
|
||||||
all: checkdirs web parser $(TARGET_OUT) $(FW_BASE)
|
espsize:
|
||||||
|
$(Q) esptool --port /dev/ttyUSB0 flash_id
|
||||||
|
|
||||||
|
espmac:
|
||||||
|
$(Q) esptool --port /dev/ttyUSB0 read_mac
|
||||||
|
|
||||||
|
all: checkdirs
|
||||||
|
$(Q) make actual_all -j4 -B
|
||||||
|
|
||||||
|
actual_all: parser $(TARGET_OUT) $(FW_BASE)
|
||||||
|
|
||||||
libesphttpd/Makefile:
|
libesphttpd/Makefile:
|
||||||
$(Q) [[ -e "libesphttpd/Makefile" ]] || echo -e "\e[31mlibesphttpd submodule missing.\nIf build fails, run \"git submodule init\" and \"git submodule update\".\e[0m"
|
$(Q) [[ -e "libesphttpd/Makefile" ]] || echo -e "\e[31mlibesphttpd submodule missing.\nIf build fails, run \"git submodule init\" and \"git submodule update\".\e[0m"
|
||||||
|
|
||||||
libesphttpd: libesphttpd/Makefile
|
libesphttpd: libesphttpd/Makefile
|
||||||
$(Q) make -C libesphttpd USE_OPENSDK=$(USE_OPENSDK) SERVERNAME_PREFIX="ESPTerm "
|
$(Q) make -C libesphttpd USE_OPENSDK=$(USE_OPENSDK) SERVERNAME_PREFIX="ESPTerm " -j4
|
||||||
|
|
||||||
$(APP_AR): libesphttpd $(OBJ)
|
$(APP_AR): libesphttpd $(OBJ)
|
||||||
$(vecho) "AR $@"
|
$(vecho) "AR $@"
|
||||||
$(Q) $(AR) cru $@ $(OBJ)
|
$(Q) $(AR) cru $@ $(OBJ)
|
||||||
|
|
||||||
checkdirs: $(BUILD_DIR)
|
checkdirs: $(BUILD_DIR) html/favicon.ico
|
||||||
|
|
||||||
|
html/favicon.ico:
|
||||||
|
$(Q) [[ -e "html/favicon.ico" ]] || ./build_web.sh
|
||||||
|
|
||||||
$(BUILD_DIR):
|
$(BUILD_DIR):
|
||||||
$(Q) mkdir -p $@
|
$(Q) mkdir -p $@
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
![Photo][photo-hw]<br>
|
![Photo][photo-hw]<br>
|
||||||
*Fig 1: Breadboard adapter developed for ESPTerm*
|
*Fig 1: Breadboard adapter developed for ESPTerm*
|
||||||
|
|
||||||
Version 1.0.0 **passes most of VTTEST test cases** (from the main menu and some Xterm specific), making it
|
As of release 1.0, ESPTerm **passes most of VTTEST test cases** (from the main menu and some Xterm specific), making it
|
||||||
functionally comparable to eg. gnome-terminal, terminator, konsole, GtkTerm or PuTTY.
|
functionally comparable to eg. gnome-terminal, terminator, konsole, GtkTerm or PuTTY.
|
||||||
ESPTerm is **capable of running Midnight Commander** through agetty, **including full
|
ESPTerm is **capable of running Midnight Commander** through agetty, **including full
|
||||||
mouse support**, provided agetty is made to believe it's Xterm, which shows ESPTerm is sufficiently well
|
mouse support**, provided agetty is made to believe it's Xterm, which shows ESPTerm is sufficiently well
|
||||||
@@ -27,23 +27,24 @@ You can try the web user interface here: [espterm.github.io][demo-term]
|
|||||||
|
|
||||||
The demo is almost identical to the real thing, except, of course, it doesn't do much without the
|
The demo is almost identical to the real thing, except, of course, it doesn't do much without the
|
||||||
emulator backend that runs on the ESP8266. The web version will be updated to match this repository
|
emulator backend that runs on the ESP8266. The web version will be updated to match this repository
|
||||||
after each minor release.
|
after each minor release (and sometimes in between for testing; the version currently being show-cased
|
||||||
|
can be read on the About page of the demo).
|
||||||
|
|
||||||
## Main features
|
## Main features
|
||||||
|
|
||||||
- **Almost complete VT102 emulation** with some extras from Xterm, eg.
|
- **Almost complete VT102 emulation** with some extras from Xterm, eg.
|
||||||
- Screen size up to 80x25
|
- Screen size up to 80x25 (the limit can be modified when compiling from source)
|
||||||
- All standard text styles and 16 colors supported
|
- All standard text styles and 16 colors supported
|
||||||
- Full UTF-8 support, alternate character sets
|
- Full UTF-8 support, alternate character sets
|
||||||
- Standard mouse tracking modes
|
- Standard mouse tracking modes
|
||||||
- You can dynamically set screen title, button labels...
|
- You can dynamically set screen title, button labels...
|
||||||
- **Web Interface**
|
- **Web Terminal Interface**
|
||||||
- Real-time screen update via WebSocket
|
- Real-time screen update via WebSocket
|
||||||
- Button to open keyboard on Android
|
- Mouse and keyboard input, works also on mobile
|
||||||
- 5 buttons under the screen for quick commands
|
- 5 optional buttons for quick commands
|
||||||
- Text file upload tool with configurable delays and line endings
|
- Text file upload tool with adjustable delays and line endings
|
||||||
- *Built-in help page* ([demo][demo-help]) with basic troubleshooting and command reference
|
- *Built-in help page* ([demo][demo-help]) with basic troubleshooting and command reference
|
||||||
- **Robust WiFi configuration interface** (Demo: [WiFi][demo-wifi], [network][demo-network] config)
|
- **User-friendly comprehensive WiFi configuration** (Demo: [WiFi][demo-wifi], [network][demo-network] config)
|
||||||
- Static IP, DHCP, channel selection, power
|
- Static IP, DHCP, channel selection, power
|
||||||
- SSID search utility for finding your existing network
|
- SSID search utility for finding your existing network
|
||||||
|
|
||||||
@@ -121,8 +122,7 @@ and changes required by the project.
|
|||||||
```
|
```
|
||||||
- Install Ragel if you wish to make modifications to the ANSI sequence parser.
|
- Install Ragel if you wish to make modifications to the ANSI sequence parser.
|
||||||
If not, comment out its call in `build_parser.sh`. The `.rl` file is the actual source, the `.c` is generated.
|
If not, comment out its call in `build_parser.sh`. The `.rl` file is the actual source, the `.c` is generated.
|
||||||
- Install Ruby and then the `sass` package with `gem install sass` (or try some other implementation, such as
|
- Install dependencies of the front-end submodule (`yarn install` in the front-end folder, installed PHP)
|
||||||
`sassc`)
|
|
||||||
- Make sure your `esphttpdconfig.mk` is set up properly - link to the SDK etc.
|
- Make sure your `esphttpdconfig.mk` is set up properly - link to the SDK etc.
|
||||||
|
|
||||||
The IoT SDK is now included in the project due to problems with obtaining the correct version and patching it.
|
The IoT SDK is now included in the project due to problems with obtaining the correct version and patching it.
|
||||||
@@ -131,24 +131,23 @@ than welcome!
|
|||||||
|
|
||||||
### Web resources
|
### Web resources
|
||||||
|
|
||||||
The web resources are in `html_orig`. To prepare for a build, run `build_web.sh`, which packs them and
|
The web resources are in the `front-end` git submodule. To prepare the web resources for a build,
|
||||||
copies over to `html`. The compression and minification is handled by scripts in libesphttpd, specifically,
|
run `make web`. The resulting files are copied to `html/`. The `html/` folder is then embedded in the firmware image.
|
||||||
it runs yuicompressor on js and css and gzip or heatshrink on the other files. The `html` folder is
|
|
||||||
then embedded in the firmware image.
|
|
||||||
|
|
||||||
It's kind of tricky to develop the web resources locally; you might want to try the "split image"
|
It's kind of tricky to develop the web resources locally; you might want to try the "split image"
|
||||||
Makefile option, then you can flash just the html portion with `make htmlflash`. I haven't tried this.
|
Makefile option, then you can flash just the html portion with `make htmlflash`. I haven't tried this.
|
||||||
|
|
||||||
For local development, use the `server.sh` script in `html_orig`. It's possible to talk to API of a running
|
For local development, use the `server.sh` script in `html_orig` (more details in the front-end repo's readme).
|
||||||
ESP8266 from here, if you configure `_env.php` with its IP.
|
It's possible to talk to the API endpoints of a running ESP8266 from a page served by your local server
|
||||||
|
if you configure `_env.php` with its IP.
|
||||||
|
|
||||||
### Flashing
|
### Flashing
|
||||||
|
|
||||||
The Makefile should automatically build the parser and web resources for you when you run `make`.
|
The Makefile should automatically build the parser and web resources for you when you run `make`.
|
||||||
Sometimes it does not, particularly with `make -B`. Try just plain `make`. You can always run those
|
The web resources are normally no re-built, because the build process is quite slow. To manually rebuild them,
|
||||||
build scripts manually, too.
|
run `make web` before `make`.
|
||||||
|
|
||||||
To flash, just run `make flash`.
|
To flash, just run `make flash`. It will use parameters you setup in the `esphttpdconfig.mk` file.
|
||||||
|
|
||||||
[releases]: https://github.com/MightyPork/esp-vt100-firmware/releases
|
[releases]: https://github.com/MightyPork/esp-vt100-firmware/releases
|
||||||
[httpdlib]: https://github.com/MightyPork/libesphttpd
|
[httpdlib]: https://github.com/MightyPork/libesphttpd
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
echo "-- Preparing WWW files --"
|
|
||||||
|
|
||||||
[[ -e html_demo ]] && rm -r html_demo
|
|
||||||
mkdir -p html_demo/img
|
|
||||||
mkdir -p html_demo/js
|
|
||||||
mkdir -p html_demo/css
|
|
||||||
|
|
||||||
cd html_orig
|
|
||||||
sh ./packjs.sh
|
|
||||||
ESP_DEMO=1 php ./build_html.php
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
cp html_orig/js/app.js html_demo/js/
|
|
||||||
|
|
||||||
sass html_orig/sass/app.scss html_demo/css/app.css
|
|
||||||
rm html_demo/css/app.css.map
|
|
||||||
|
|
||||||
cp html_orig/img/* html_demo/img/
|
|
||||||
cp html_orig/favicon.ico html_demo/favicon.ico
|
|
||||||
|
|
||||||
# cleanup
|
|
||||||
find html_demo/ -name "*.orig" -delete
|
|
||||||
find html_demo/ -name "*.xcf" -delete
|
|
||||||
find html_demo/ -name "*~" -delete
|
|
||||||
+3
-18
@@ -3,24 +3,9 @@
|
|||||||
echo "-- Preparing WWW files --"
|
echo "-- Preparing WWW files --"
|
||||||
|
|
||||||
[[ -e html ]] && rm -r html
|
[[ -e html ]] && rm -r html
|
||||||
mkdir -p html/img
|
|
||||||
mkdir -p html/js
|
|
||||||
mkdir -p html/css
|
|
||||||
|
|
||||||
cd html_orig
|
ESP_PROD=1 front-end/build.sh
|
||||||
sh ./packjs.sh
|
|
||||||
php ./build_html.php
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
cp html_orig/js/app.js html/js/
|
echo "Copying from submodule..."
|
||||||
|
|
||||||
sass html_orig/sass/app.scss html/css/app.css
|
cp -r front-end/out html
|
||||||
rm html/css/app.css.map
|
|
||||||
|
|
||||||
cp html_orig/img/* html/img/
|
|
||||||
cp html_orig/favicon.ico html/favicon.ico
|
|
||||||
|
|
||||||
# cleanup
|
|
||||||
find html/ -name "*.orig" -delete
|
|
||||||
find html/ -name "*.xcf" -delete
|
|
||||||
find html/ -name "*~" -delete
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
./build_demo.sh
|
|
||||||
|
|
||||||
cp -r html_demo/* ../espterm.github.io/
|
|
||||||
|
|
||||||
cd ../espterm.github.io/
|
|
||||||
|
|
||||||
echo "Enter to deploy (^C to abort):"
|
|
||||||
read
|
|
||||||
|
|
||||||
git add --all
|
|
||||||
git commit -m "Deploy updates"
|
|
||||||
git push
|
|
||||||
@@ -35,9 +35,9 @@
|
|||||||
#define os_snprintf ets_snprintf
|
#define os_snprintf ets_snprintf
|
||||||
|
|
||||||
#ifdef USE_OPTIMIZE_PRINTF
|
#ifdef USE_OPTIMIZE_PRINTF
|
||||||
#define os_printf(fmt, ...) do { \
|
#define os_printf(fmt, ...) do { \
|
||||||
static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = fmt; \
|
static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = fmt; \
|
||||||
os_printf_plus(flash_str, ##__VA_ARGS__); \
|
os_printf_plus(flash_str, ##__VA_ARGS__); \
|
||||||
} while(0)
|
} while(0)
|
||||||
#else
|
#else
|
||||||
#define os_printf os_printf_plus
|
#define os_printf os_printf_plus
|
||||||
|
|||||||
+11
-5
@@ -18,7 +18,7 @@ GZIP_COMPRESSION = yes
|
|||||||
# This option works only when GZIP_COMPRESSION is set to "yes"
|
# This option works only when GZIP_COMPRESSION is set to "yes"
|
||||||
# http://yui.github.io/yuicompressor/
|
# http://yui.github.io/yuicompressor/
|
||||||
#Disabled by default.
|
#Disabled by default.
|
||||||
COMPRESS_W_YUI = yes
|
COMPRESS_W_YUI = no
|
||||||
|
|
||||||
YUI-COMPRESSOR = /usr/bin/yui-compressor
|
YUI-COMPRESSOR = /usr/bin/yui-compressor
|
||||||
|
|
||||||
@@ -44,14 +44,20 @@ ADMIN_PASSWORD = "19738426"
|
|||||||
GLOBAL_CFLAGS = \
|
GLOBAL_CFLAGS = \
|
||||||
-DDEBUG_ROUTER=0 \
|
-DDEBUG_ROUTER=0 \
|
||||||
-DDEBUG_CAPTDNS=0 \
|
-DDEBUG_CAPTDNS=0 \
|
||||||
-DDEBUG_HTTP=1 \
|
-DDEBUG_HTTP=0 \
|
||||||
-DDEBUG_ESPFS=0 \
|
-DDEBUG_ESPFS=0 \
|
||||||
|
-DDEBUG_PERSIST=0 \
|
||||||
|
-DDEBUG_UTFCACHE=0 \
|
||||||
|
-DDEBUG_CGI=0 \
|
||||||
|
-DDEBUG_WIFI=0 \
|
||||||
-DDEBUG_WS=0 \
|
-DDEBUG_WS=0 \
|
||||||
-DDEBUG_ANSI=1 \
|
-DDEBUG_ANSI=1 \
|
||||||
-DDEBUG_ANSI_NOIMPL=1 \
|
-DDEBUG_ANSI_NOIMPL=1 \
|
||||||
|
-DDEBUG_INPUT=0 \
|
||||||
|
-DDEBUG_HEAP=1 \
|
||||||
|
-DDEBUG_MALLOC=0 \
|
||||||
-DHTTPD_MAX_BACKLOG_SIZE=8192 \
|
-DHTTPD_MAX_BACKLOG_SIZE=8192 \
|
||||||
-DHTTPD_MAX_HEAD_LEN=1024 \
|
-DHTTPD_MAX_HEAD_LEN=1024 \
|
||||||
-DHTTPD_MAX_POST_LEN=512 \
|
-DHTTPD_MAX_POST_LEN=512 \
|
||||||
-DDEBUG_INPUT=0 \
|
-mforce-l32 \
|
||||||
-DDEBUG_HEAP=1 \
|
-DUSE_OPTIMIZE_PRINTF=1
|
||||||
-DDEBUG_MALLOC=0
|
|
||||||
|
|||||||
Submodule
+1
Submodule front-end added at b2174fc528
@@ -1 +0,0 @@
|
|||||||
pages/_test_env.php
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Those replacements are done by the development server to test it locally
|
|
||||||
* without esphttpd. This is needed mainly for places where the replacements
|
|
||||||
* are given to JavaScript, to avoid syntax errors with
|
|
||||||
*/
|
|
||||||
|
|
||||||
$vers = '???';
|
|
||||||
$f = file_get_contents(__DIR__ . '/../user/version.h');
|
|
||||||
preg_match_all('/#define FW_V_.*? (\d+)/', $f, $vm);
|
|
||||||
#define FW_V_MAJOR 1
|
|
||||||
#define FW_V_MINOR 0
|
|
||||||
#define FW_V_PATCH 0
|
|
||||||
|
|
||||||
$vers = $vm[1][0].'.'.$vm[1][1].'.'.$vm[1][2];
|
|
||||||
|
|
||||||
return [
|
|
||||||
'term_title' => ESP_DEMO ? 'ESPTerm Web UI Demo' : 'ESPTerm local debug',
|
|
||||||
|
|
||||||
'btn1' => 'OK',
|
|
||||||
'btn2' => 'Cancel',
|
|
||||||
'btn3' => '',
|
|
||||||
'btn4' => '',
|
|
||||||
'btn5' => 'Help',
|
|
||||||
'bm1' => '01,'.ord('y'),
|
|
||||||
'bm2' => '01,'.ord('n'),
|
|
||||||
'bm3' => '',
|
|
||||||
'bm4' => '',
|
|
||||||
'bm5' => '05',
|
|
||||||
'labels_seq' => ESP_DEMO ? 'TESPTerm Web UI DemoOKCancelHelp' : 'TESPTerm local debugOKCancelHelp',
|
|
||||||
|
|
||||||
'parser_tout_ms' => 10,
|
|
||||||
'display_tout_ms' => 15,
|
|
||||||
'display_cooldown_ms' => 35,
|
|
||||||
'fn_alt_mode' => '1',
|
|
||||||
|
|
||||||
'opmode' => '2',
|
|
||||||
'sta_enable' => '1',
|
|
||||||
'ap_enable' => '1',
|
|
||||||
|
|
||||||
'tpw' => '60',
|
|
||||||
'ap_channel' => '7',
|
|
||||||
'ap_ssid' => 'TERM-027451',
|
|
||||||
'ap_password' => '',
|
|
||||||
'ap_hidden' => '0',
|
|
||||||
|
|
||||||
'sta_ssid' => 'Cisco',
|
|
||||||
'sta_password' => 'Passw0rd!',
|
|
||||||
'sta_active_ip' => ESP_DEMO ? '192.168.82.66' : '192.168.0.19',
|
|
||||||
'sta_active_ssid' => 'Cisco',
|
|
||||||
|
|
||||||
'vers_fw' => $vers,
|
|
||||||
'date' => date('Y-m-d'),
|
|
||||||
'time' => date('G:i'),
|
|
||||||
'vers_httpd' => '0.4',
|
|
||||||
'vers_sdk' => '010502',
|
|
||||||
'githubrepo' => 'https://github.com/MightyPork/esp-vt100-firmware',
|
|
||||||
|
|
||||||
'ap_dhcp_time' => '120',
|
|
||||||
'ap_dhcp_start' => '192.168.4.100',
|
|
||||||
'ap_dhcp_end' => '192.168.4.200',
|
|
||||||
'ap_addr_ip' => '192.168.4.1',
|
|
||||||
'ap_addr_mask' => '255.255.255.0',
|
|
||||||
|
|
||||||
'sta_dhcp_enable' => '1',
|
|
||||||
'sta_addr_ip' => '192.168.0.33',
|
|
||||||
'sta_addr_mask' => '255.255.255.0',
|
|
||||||
'sta_addr_gw' => '192.168.0.1',
|
|
||||||
|
|
||||||
'sta_mac' => '5c:cf:7f:02:74:51',
|
|
||||||
'ap_mac' => '5e:cf:7f:02:74:51',
|
|
||||||
|
|
||||||
'term_width' => '80',
|
|
||||||
'term_height' => '25',
|
|
||||||
'default_bg' => '0',
|
|
||||||
'default_fg' => '7',
|
|
||||||
'show_buttons' => '1',
|
|
||||||
'show_config_links' => '1',
|
|
||||||
|
|
||||||
'uart_baud' => 115200,
|
|
||||||
'uart_stopbits' => 1,
|
|
||||||
'uart_parity' => 2,
|
|
||||||
|
|
||||||
'theme' => 0,
|
|
||||||
];
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
define("ESP_IP", "192.168.0.19");
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
define("ESP_IP", "192.168.0.19");
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
$pages = [];
|
|
||||||
|
|
||||||
if (! function_exists('pg')) {
|
|
||||||
/** Add a page */
|
|
||||||
function pg($key, $bc, $icon, $path, $titleKey = null)
|
|
||||||
{
|
|
||||||
global $pages;
|
|
||||||
$pages[$key] = (object) [
|
|
||||||
'key' => $key,
|
|
||||||
'bodyclass' => $bc,
|
|
||||||
'path' => $path,
|
|
||||||
'icon' => $icon ? "icn-$icon" : '',
|
|
||||||
'label' => tr("menu.$key"),
|
|
||||||
'title' => $titleKey ? tr($titleKey) : tr("menu.$key"),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pg('cfg_term', 'cfg', 'terminal', '/cfg/term');
|
|
||||||
pg('term_set', 'api', '', '/cfg/term/set');
|
|
||||||
|
|
||||||
pg('cfg_wifi', 'cfg', 'wifi', '/cfg/wifi');
|
|
||||||
pg('cfg_wifi_conn', '', '', '/cfg/wifi/connecting');
|
|
||||||
pg('wifi_connstatus', 'api', '', '/cfg/wifi/connstatus');
|
|
||||||
pg('wifi_set', 'api', '', '/cfg/wifi/set');
|
|
||||||
pg('wifi_scan', 'api', '', '/cfg/wifi/scan');
|
|
||||||
|
|
||||||
pg('cfg_network', 'cfg', 'network', '/cfg/network');
|
|
||||||
pg('network_set', 'api', '', '/cfg/network/set');
|
|
||||||
|
|
||||||
pg('cfg_system', 'cfg', 'configure', '/cfg/system');
|
|
||||||
pg('system_set', 'api', '', '/cfg/system/set');
|
|
||||||
|
|
||||||
pg('write_defaults', 'api', '', '/cfg/system/write_defaults');
|
|
||||||
pg('restore_defaults', 'api', '', '/cfg/system/restore_defaults');
|
|
||||||
pg('restore_hard', 'api', '', '/cfg/system/restore_hard');
|
|
||||||
|
|
||||||
pg('help', 'cfg page-help', 'help', '/help');
|
|
||||||
pg('about', 'cfg page-about', 'about', '/about');
|
|
||||||
pg('term', 'term', '', '/', 'title.term');
|
|
||||||
|
|
||||||
pg('reset_screen', 'api', '', '/system/cls', 'title.term');
|
|
||||||
|
|
||||||
pg('index', 'api', '', '/', '');
|
|
||||||
|
|
||||||
// ajax API
|
|
||||||
|
|
||||||
return $pages;
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The common stuff required by both index.php and build_html.php
|
|
||||||
* this must be required_once
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (defined('BASE_INITED')) return;
|
|
||||||
define('BASE_INITED', true);
|
|
||||||
|
|
||||||
if (!empty($argv[1])) {
|
|
||||||
parse_str($argv[1], $_GET);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists(__DIR__ . '/_env.php')) {
|
|
||||||
die("Copy <b>_env.php.example</b> to <b>_env.php</b> and check the settings inside!");
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once __DIR__ . '/_env.php';
|
|
||||||
|
|
||||||
$prod = defined('STDIN');
|
|
||||||
define('DEBUG', !$prod);
|
|
||||||
$root = DEBUG ? json_encode(ESP_IP) : 'location.host';
|
|
||||||
define('JS_WEB_ROOT', $root);
|
|
||||||
|
|
||||||
define('ESP_DEMO', (bool)getenv('ESP_DEMO'));
|
|
||||||
if (ESP_DEMO) {
|
|
||||||
define('DEMO_SCREEN', '"S\u0019\u0001Q\u0001\u0017\u0001K\u0001\u0015\u0004\u0003\b\u0001 \u0002P\u0001┌ESPTerm─Demo─\u0002\u0002\u0001\u0003\u0002\u000131\u0003\u0003\u000132\u0003\u0004\u00013\u0002\u0002\u0001\u0003\u0005\u000134\u0003\u0006\u000135\u0003\u0007\u000136\u0003\b\u000137\u0003\t\u000190\u0003\n\u000191\u0003\u000b\u000192\u0003\f\u000193\u0003\r\u000194\u0003\u000e\u000195\u0003\u000f\u000196\u0003\u0010\u000197\u0003\b\u0001─\u0002\r\u0001┐ \u0002\u0015\u0001│ \u00029\u0001│ \u0002\u0004\u0001│\u0002\t\u0001 \u0002\b\u0001│\u0004\u0002\u0001Bold \u0004\u0003\u0001F\u0004\u0003\u0001a\u0004\u0003\u0001i\u0004\u0003\u0001n\u0004\u0003\u0001t\u0004\u0003\u0001 \u0004\u0005\u0001I\u0004\u0005\u0001t\u0004\u0005\u0001a\u0004\u0005\u0001l\u0004\u0005\u0001i\u0004\u0005\u0001c\u0004\u0005\u0001 \u0004\t\u0001U\u0004\t\u0001n\u0004\t\u0001d\u0004\t\u0001e\u0004\t\u0001r\u0004\t\u0001l\u0004\t\u0001i\u0004\t\u0001n\u0004\t\u0001e\u0004\u0001\u0001 \u0004\u0011\u0001B\u0004\u0011\u0001l\u0004\u0011\u0001i\u0004\u0011\u0001n\u0004\u0011\u0001k\u0004\u0011\u0001 \u0001q\u0001\u0001Inverse\u0003\b\u0001 \u0004A\u0001S\u0004A\u0001t\u0004A\u0001r\u0004A\u0001i\u0004A\u0001k\u0004A\u0001e\u0004\u0001\u0001 \u0004!\u0001F\u0004!\u0001r\u0004!\u0001a\u0004!\u0001k\u0004!\u0001t\u0004!\u0001u\u0004!\u0001r\u0004\u0001\u0001 │ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0002\t\u0001\u0003\b\u0001─\u0002\u0002\u0001 \u0002\u0006\u0001│ \u00029\u0001│ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0003\u0002\u0002ESP826\u0002\u0002\u0001\u0003\n\u0002 \u0003\b\u0001─\u0002\u0002\u0001 \u0002\u0006\u0001└─\u00029\u0001┤ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0002\t\u0001\u0003\b\u0001─\u0002\u0002\u0001 \u0002@\u0001│ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0003\u0002\u0002(@)#\u0002\u0004\u0001\u0003\n\u0002 \u0003\b\u0001─\u0002\u0002\u0001 \u0002\u0007\u0001\u0003O\u0001 This is a static demo of the ESPTerm Web Interface \u0002\u0004\u0001\u0003\b\u0001 \u0002\u0002\u0001│ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0002\t\u0001\u0003\b\u0001─\u0002\u0002\u0001 \u0002\u0007\u0001\u0003O\u0001 \u00027\u0001\u0003\b\u0001 \u0002\u0002\u0001│ \u0002\u0004\u0001│\u0002\t\u0001 \u0002\t\u0001\u0003O\u0001 Try the links beneath this scre\u0002\u0002\u0001n to browse the menu. \u0003\b\u0001 \u0002\u0002\u0001♦ \u0002\u0016\u0001\u0003O\u0001 \u00027\u0001\u0003\b\u0001 \u0002\u0019\u0001\u0003O\u0001 <°)\u0002\u0003\u0001>< ESPTerm ful\u0002\u0002\u0001y sup\u0002\u0002\u0001orts UTF-8 お は よ ー \u0002\u0002\u0001><(\u0002\u0003\u0001°> \u0003\b\u0001 \u0002\u0019\u0001\u0003O\u0001 \u00027\u0001\u0003\b\u0001 \u0002i\u0001\u0003\u000b\u0001Other interesting features:\u0003\b\u0001 \u0002\u0018\u0001↓ \u0002n\u0001\u0003\u0003\u0001- Almost ful\u0002\u0002\u0001 VT10\u0002\u0002\u0001 emulation \u0003\b\u0001 \u0003\u0006\u0001()\u0003\b\u0001 \u0003\u0006\u0001()\u0003\b\u0001 \u0002\b\u0001Funguje tu čeština! \u0002\u0011\u0001\u0003\u0005\u0001- Xterm-like mouse tracking\u0003\b\u0001 \u0002\u0003\u0001=\u0002\u0002\u0001\u0003\t\u0002°.°\u0003\b\u0001=\u0002\u0002\u0001 \u0003\u0006\u0001<-\u0002\u0003\u0001, \u0003\b\u0001 \u0002$\u0001\u0003\u0004\u0001- File upload utility\u0003\b\u0001 \u0002\n\u0001\'\u0002\u0002\u0001 \'\u0002\u0002\u0001 \u0002\u0002\u0001\u0003\u0006\u0001 \u0002\u0004\u0001mouse\u0003\b\u0001 \u0002!\u0001\u0003\u0002\u0001- User-friendly config interface\u0003\b\u0001 \u00020\u0001\u0003\u000e\u0001-\u0003\u0002\u0001 \u0003\u000e\u0001Advanced WiFi & network set\u0002\u0002\u0001ings\u0003\b\u0001 \u0002\u0011\u0001\u0003\f\u0001Try ESPTerm today!\u0003\b\u0001 \u0002\u000b\u0001- Built-in help page \u0002\u001a\u0001\u0003\u0007\u0001-\u0002\u0002\u0001>\u0003\b\u0001 \u0002\u0002\u0001\u0003\f\u0001Pre-built binaries\u0003\b\u0001 \u0003\f\u0001are\u0003\b\u0001 \u0002\"\u0001\u0003\u0007\u0001link on the About page \u0002\u0002\u0001\u0003\f\u0001available on GitHub! \u0003\b\u0001 \u0002U\u0001"');
|
|
||||||
define('DEMO_APS', <<<APS
|
|
||||||
{
|
|
||||||
"result": {
|
|
||||||
"inProgress": 0,
|
|
||||||
"APs": [
|
|
||||||
{"essid": "Cisco", "bssid": "88:f7:c7:52:b3:99", "rssi": 205, "rssi_perc": 100, "enc": 4, "channel": 7},
|
|
||||||
{"essid": "UPC Wi-Free", "bssid": "8a:f7:c7:52:b3:9b", "rssi": 203, "rssi_perc": 100, "enc": 5, "channel": 1},
|
|
||||||
{"essid": "UPC Wi-Free", "bssid": "0a:95:2a:0c:84:31", "rssi": 166, "rssi_perc": 32, "enc": 5, "channel": 1},
|
|
||||||
{"essid": "MujO2Internet_2EEB96", "bssid": "d0:60:8c:2e:eb:96", "rssi": 174, "rssi_perc": 48, "enc": 4, "channel": 4},
|
|
||||||
{"essid": "Internet", "bssid": "38:72:c0:32:bd:0d", "rssi": 164, "rssi_perc": 28, "enc": 2, "channel": 10},
|
|
||||||
{"essid": "MyO2Internet_08C850", "bssid": "78:c1:a7:08:c8:50", "rssi": 186, "rssi_perc": 72, "enc": 4, "channel": 11},
|
|
||||||
{"essid": "UPC Wi-Free", "bssid": "06:7c:34:9a:6f:7c", "rssi": 167, "rssi_perc": 34, "enc": 0, "channel": 11},
|
|
||||||
{"essid": "Internet_B0", "bssid": "5c:f4:ab:11:3b:b3", "rssi": 175, "rssi_perc": 50, "enc": 3, "channel": 13},
|
|
||||||
{"essid": "UPC5716805", "bssid": "08:95:2a:0c:84:3f", "rssi": 165, "rssi_perc": 30, "enc": 4, "channel": 1}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
APS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
define('LOCALE', isset($_GET['locale']) ? $_GET['locale'] : 'en');
|
|
||||||
|
|
||||||
$_messages = require(__DIR__ . '/lang/' . LOCALE . '.php');
|
|
||||||
$_pages = require(__DIR__ . '/_pages.php');
|
|
||||||
|
|
||||||
define('APP_NAME', 'ESPTerm');
|
|
||||||
|
|
||||||
/** URL (dev or production) */
|
|
||||||
function url($name, $relative = false)
|
|
||||||
{
|
|
||||||
global $_pages;
|
|
||||||
if ($relative) return $_pages[$name]->path;
|
|
||||||
|
|
||||||
if (DEBUG) return "/index.php?page=$name";
|
|
||||||
if (ESP_DEMO) return "$name.html";
|
|
||||||
else return $_pages[$name]->path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** URL label for a button */
|
|
||||||
function label($name)
|
|
||||||
{
|
|
||||||
global $_pages;
|
|
||||||
return $_pages[$name]->label;
|
|
||||||
}
|
|
||||||
|
|
||||||
function e($s)
|
|
||||||
{
|
|
||||||
return htmlspecialchars($s, ENT_HTML5 | ENT_QUOTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
function je($s)
|
|
||||||
{
|
|
||||||
return htmlspecialchars(json_encode($s), ENT_HTML5);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function tr($key)
|
|
||||||
{
|
|
||||||
global $_messages;
|
|
||||||
return isset($_messages[$key]) ? $_messages[$key] : ('??' . $key . '??');
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Like eval, but allows <?php and ?> */
|
|
||||||
function include_str($code)
|
|
||||||
{
|
|
||||||
$tmp = tmpfile();
|
|
||||||
$tmpf = stream_get_meta_data($tmp);
|
|
||||||
$tmpf = $tmpf ['uri'];
|
|
||||||
fwrite($tmp, $code);
|
|
||||||
$ret = include($tmpf);
|
|
||||||
fclose($tmp);
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('utf8')) {
|
|
||||||
function utf8($num)
|
|
||||||
{
|
|
||||||
if($num<=0x7F) return chr($num);
|
|
||||||
if($num<=0x7FF) return chr(($num>>6)+192).chr(($num&63)+128);
|
|
||||||
if($num<=0xFFFF) return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
|
|
||||||
if($num<=0x1FFFFF) return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128).chr(($num&63)+128);
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('load_esp_charsets')) {
|
|
||||||
function load_esp_charsets() {
|
|
||||||
$chsf = __DIR__ . '/../user/character_sets.h';
|
|
||||||
$re_table = '/\/\/ %%BEGIN:(.)%%\s*(.*?)\s*\/\/ %%END:\1%%/s';
|
|
||||||
preg_match_all($re_table, file_get_contents($chsf), $m_tbl);
|
|
||||||
|
|
||||||
$re_bounds = '/#define CODEPAGE_(.)_BEGIN\s+(\d+)\n#define CODEPAGE_\1_END\s+(\d+)/';
|
|
||||||
preg_match_all($re_bounds, file_get_contents($chsf), $m_bounds);
|
|
||||||
|
|
||||||
$cps = [];
|
|
||||||
|
|
||||||
foreach ($m_tbl[2] as $i => $str) {
|
|
||||||
$name = $m_tbl[1][$i];
|
|
||||||
$start = intval($m_bounds[2][$i]);
|
|
||||||
$table = [];
|
|
||||||
$str = preg_replace('/,\s*\/\/[^\n]*/', '', $str);
|
|
||||||
$rows = explode("\n", $str);
|
|
||||||
$rows = array_map('trim', $rows);
|
|
||||||
|
|
||||||
foreach($rows as $j => $v) {
|
|
||||||
if (strpos($v, '0x') === 0) {
|
|
||||||
$v = substr($v, 2);
|
|
||||||
$v = hexdec($v);
|
|
||||||
} else {
|
|
||||||
$v = intval($v);
|
|
||||||
}
|
|
||||||
$ascii = $start+$j;
|
|
||||||
$table[] = [
|
|
||||||
$ascii,
|
|
||||||
chr($ascii),
|
|
||||||
utf8($v==0? $ascii :$v),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$cps[$name] = $table;
|
|
||||||
}
|
|
||||||
return $cps;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('tplSubs')) {
|
|
||||||
function tplSubs($str, $reps)
|
|
||||||
{
|
|
||||||
return preg_replace_callback('/%(j:|js:|h:|html:)?([a-z0-9-_.]+)%/i', function ($m) use ($reps) {
|
|
||||||
$key = $m[2];
|
|
||||||
if (array_key_exists($key, $reps)) {
|
|
||||||
$val = $reps[$key];
|
|
||||||
} else {
|
|
||||||
$val = '';
|
|
||||||
}
|
|
||||||
switch ($m[1]) {
|
|
||||||
case 'j:':
|
|
||||||
case 'js:':
|
|
||||||
$v = json_encode($val);
|
|
||||||
return substr($v, 1, strlen($v) - 2);
|
|
||||||
case 'h:':
|
|
||||||
case 'html:':
|
|
||||||
return htmlspecialchars($val);
|
|
||||||
default:
|
|
||||||
return $val;
|
|
||||||
}
|
|
||||||
}, $str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/base.php';
|
|
||||||
|
|
||||||
function process_html($s) {
|
|
||||||
$pattern = '/<!--(.*)-->/Uis';
|
|
||||||
$s = preg_replace($pattern, '', $s);
|
|
||||||
|
|
||||||
$pattern = '/(?:(?:\/\*(?:[^*]|(?:\*+[^*\/]))*\*+\/)|(?:(?<!\:|\\\|\'|\")\/\/.*))/';
|
|
||||||
$s = preg_replace($pattern, '', $s);
|
|
||||||
|
|
||||||
$pattern = '/\s+/s';
|
|
||||||
$s = preg_replace($pattern, ' ', $s);
|
|
||||||
return $s;
|
|
||||||
}
|
|
||||||
|
|
||||||
$no_tpl_files = ['help', 'cfg_wifi_conn'];
|
|
||||||
|
|
||||||
$dest = ESP_DEMO ? __DIR__ . '/../html_demo/' : __DIR__ . '/../html/';
|
|
||||||
|
|
||||||
ob_start();
|
|
||||||
foreach($_pages as $_k => $p) {
|
|
||||||
if ($p->bodyclass == 'api') {
|
|
||||||
if (ESP_DEMO) {
|
|
||||||
$target = 'term.html';
|
|
||||||
echo "Generating: ~$_k.html -> $target\n";
|
|
||||||
$s = "<!DOCTYPE HTML><meta http-equiv=\"refresh\" content=\"0;url=$target\">";
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
echo "Generating: $_k ($p->title)\n";
|
|
||||||
|
|
||||||
$_GET['page'] = $_k;
|
|
||||||
ob_flush(); // print the message
|
|
||||||
ob_clean(); // clean up
|
|
||||||
include(__DIR__ . '/index.php');
|
|
||||||
$s = ob_get_contents(); // grab the output
|
|
||||||
|
|
||||||
// remove newlines and comments
|
|
||||||
// as tests have shown, it saves just a couple kilobytes,
|
|
||||||
// making it not a very big improvement at the expense of ugly html.
|
|
||||||
// $s = process_html($s);
|
|
||||||
ob_clean();
|
|
||||||
} // clean up
|
|
||||||
$of = $dest . $_k . ((in_array($_k, $no_tpl_files)||ESP_DEMO) ? '.html' : '.tpl');
|
|
||||||
file_put_contents($of, $s); // write to a file
|
|
||||||
}
|
|
||||||
|
|
||||||
ob_flush();
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/* This script is run on demand to generate JS version of tr() */
|
|
||||||
|
|
||||||
require_once __DIR__ . '/base.php';
|
|
||||||
|
|
||||||
$selected = [
|
|
||||||
'wifi.connected_ip_is',
|
|
||||||
'wifi.not_conn',
|
|
||||||
'wifi.enter_passwd',
|
|
||||||
'wifi.passwd_saved',
|
|
||||||
];
|
|
||||||
|
|
||||||
$out = [];
|
|
||||||
foreach ($selected as $key) {
|
|
||||||
$out[$key] = $_messages[$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
file_put_contents(__DIR__. '/jssrc/lang.js',
|
|
||||||
"// Generated from PHP locale file\n" .
|
|
||||||
'var _tr = ' . json_encode($out, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE) . ";\n\n" .
|
|
||||||
"function tr(key) { return _tr[key] || '?'+key+'?'; }\n"
|
|
||||||
);
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 318 B |
@@ -1 +0,0 @@
|
|||||||
/out/
|
|
||||||
Binary file not shown.
@@ -1,93 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# resolve current file's directory
|
|
||||||
DIR=$(dirname $(realpath $0))
|
|
||||||
|
|
||||||
OUTPUT_DIR="$DIR/out"
|
|
||||||
SASS_DIR="$DIR/../sass"
|
|
||||||
|
|
||||||
ICON_PREFIX='icn'
|
|
||||||
|
|
||||||
# list with full paths, sort from newest
|
|
||||||
NEWEST=$(ls -dt1 "$DIR"/*.zip | head -1)
|
|
||||||
|
|
||||||
if [[ -z "$NEWEST" ]]; then
|
|
||||||
echo "Fontello zip not found."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clean the output folder
|
|
||||||
rm -rf "$OUTPUT_DIR"
|
|
||||||
mkdir -p "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
echo "Unpacking fontello..."
|
|
||||||
|
|
||||||
unzip -ju "$NEWEST" -d "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
echo "Patching paths in the fontello CSS..."
|
|
||||||
|
|
||||||
# Fix bad relative paths in the CSS
|
|
||||||
sed -i "s|\.\./font/|/fonts/|g" "$OUTPUT_DIR/"*.css
|
|
||||||
|
|
||||||
echo "Generating SASS file with icon codes..."
|
|
||||||
|
|
||||||
SASSFILE="$SASS_DIR/_fontello.scss"
|
|
||||||
|
|
||||||
echo -e "@charset \"UTF-8\";\n\n/* Fontello data, processed by the unpack script. */\n" > "$SASSFILE"
|
|
||||||
|
|
||||||
# Extract the base font-face style
|
|
||||||
#grep -Pazo "(?s)@font-face.*?normal;\n\}" "$OUTPUT_DIR/fontello.css" \
|
|
||||||
# | sed 's/\x0//g' >> "$SASSFILE"
|
|
||||||
|
|
||||||
grep -Pazo "(?s)@font-face \{\n\s*font-family: 'fontello';\n\s*src: url\('data.*?woff'\)" "$OUTPUT_DIR/fontello-embedded.css" \
|
|
||||||
| sed 's/\x0//g' >> "$SASSFILE"
|
|
||||||
|
|
||||||
echo -e ";\n}" >> "$SASSFILE"
|
|
||||||
|
|
||||||
|
|
||||||
grep -Pazo "(?s)$ICON_PREFIX-\"\]:before .*?\}" "$OUTPUT_DIR/fontello.css" \
|
|
||||||
| sed 's/\x0//g' \
|
|
||||||
| sed "s/$ICON_PREFIX-\"\]:before/\n\n%fontello-icon-base \{\n\&::before /g" \
|
|
||||||
>> "$SASSFILE"
|
|
||||||
echo -e "\n}" >> "$SASSFILE"
|
|
||||||
|
|
||||||
echo -e "\n\n/* Fontello icon codes */" >> "$SASSFILE"
|
|
||||||
echo -n "\$icon-codes: (" >> "$SASSFILE"
|
|
||||||
sed -r "s|\.$ICON_PREFIX-([a-z0-9-]+):before \{ content: ('.*?');.*?$|\t\1: \2,|g" "$OUTPUT_DIR/fontello-codes.css" \
|
|
||||||
| sed -r "s|@.*||g" >> "$SASSFILE"
|
|
||||||
|
|
||||||
echo -ne "\n);\n" >> "$SASSFILE"
|
|
||||||
|
|
||||||
echo -ne "\n/* Fontello classes */" >> "$SASSFILE"
|
|
||||||
cat "$OUTPUT_DIR/fontello-codes.css" \
|
|
||||||
| sed -r 's/\/\*.+\*\///g' \
|
|
||||||
| sed -r "s|@.*||g" \
|
|
||||||
| sed 's/:before/::before/g' >> "$SASSFILE"
|
|
||||||
|
|
||||||
TAIL=$(cat <<ASDF
|
|
||||||
|
|
||||||
|
|
||||||
[class^="$ICON_PREFIX-"], [class*=" $ICON_PREFIX-"] {
|
|
||||||
@extend %fontello-icon-base;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin icon-base() {
|
|
||||||
@extend %fontello-icon-base;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin icon-content(\$icon-name) {
|
|
||||||
&::before {
|
|
||||||
content: map-get(\$icon-codes, \$icon-name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin icon(\$icon-name) {
|
|
||||||
@include icon-base();
|
|
||||||
@include icon-content(\icon-name);
|
|
||||||
}
|
|
||||||
ASDF
|
|
||||||
)
|
|
||||||
|
|
||||||
echo "$TAIL" >> "$SASSFILE"
|
|
||||||
|
|
||||||
echo -e "\e[32mFontello ready\e[0m"
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 8.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
@@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/base.php';
|
|
||||||
|
|
||||||
if (!isset($_GET['page'])) $_GET['page'] = 'term';
|
|
||||||
|
|
||||||
$_GET['PAGE_TITLE'] = $_pages[$_GET['page']]->title . ' :: ' . APP_NAME;
|
|
||||||
$_GET['BODYCLASS'] = $_pages[$_GET['page']]->bodyclass;
|
|
||||||
|
|
||||||
$_pf = __DIR__ . '/pages/'.$_GET['page'].'.php';
|
|
||||||
|
|
||||||
if (!file_exists($_pf)) {
|
|
||||||
header("Location: /", true, 302);
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
require __DIR__ . '/pages/_head.php';
|
|
||||||
|
|
||||||
$include_re = '/<\?php\s*(require|include)\s*\(?\s*?(?:__DIR__\s*\.)?\s*(["\'])(.*?)\2\s*\)?;\s*\?>/';
|
|
||||||
|
|
||||||
if (file_exists($_pf)) {
|
|
||||||
$f = file_get_contents($_pf);
|
|
||||||
|
|
||||||
// Resolve requires inline - they wont work after dumping the resulting file to /tmp for eval
|
|
||||||
$f = preg_replace_callback($include_re, function ($m) use ($_pf) {
|
|
||||||
$n = dirname($_pf).'/'.$m[3];
|
|
||||||
if (file_exists($n)) {
|
|
||||||
return file_get_contents($n);
|
|
||||||
} else {
|
|
||||||
return "<p>NOT FOUND: $n</p>";
|
|
||||||
}
|
|
||||||
}, $f);
|
|
||||||
|
|
||||||
if (DEBUG || ESP_DEMO)
|
|
||||||
$str = tplSubs($f, require(__DIR__ . '/_debug_replacements.php'));
|
|
||||||
else $str = $f;
|
|
||||||
|
|
||||||
// special symbols
|
|
||||||
$str = str_replace('\,', ' ', $str);
|
|
||||||
$str = preg_replace('/(?<=[^ \\\\])~(?=[^ ])/', ' ', $str);
|
|
||||||
$str = str_replace('\~', '~', $str);
|
|
||||||
$str = preg_replace('/(?<![\w\\\\])`([^ `][^`]*?[^ `]|[^ `])`(?!\w)/', '<code>$1</code>', $str);
|
|
||||||
$str = preg_replace('/(?<![\w\\\\])_([^ _][^_]*?[^ _]|[^ _])_(?!\w)/', '<i>$1</i>', $str);
|
|
||||||
$str = preg_replace('/(?<![\w\\\\])\*([^ *][^*]*?[^ *]|[^ *])\*(?!\w)/', '<b>$1</b>', $str);
|
|
||||||
|
|
||||||
$str = preg_replace("/\s*(\\\\\\\\)[\n \t]+/", '<br>', $str);
|
|
||||||
include_str($str);
|
|
||||||
}
|
|
||||||
|
|
||||||
require __DIR__ . '/pages/_tail.php';
|
|
||||||
-2533
File diff suppressed because it is too large
Load Diff
@@ -1,189 +0,0 @@
|
|||||||
/** Global generic init */
|
|
||||||
$.ready(function () {
|
|
||||||
// Checkbox UI (checkbox CSS and hidden input with int value)
|
|
||||||
$('.Row.checkbox').forEach(function(x) {
|
|
||||||
var inp = x.querySelector('input');
|
|
||||||
var box = x.querySelector('.box');
|
|
||||||
|
|
||||||
$(box).toggleClass('checked', inp.value);
|
|
||||||
|
|
||||||
var hdl = function() {
|
|
||||||
inp.value = 1 - inp.value;
|
|
||||||
$(box).toggleClass('checked', inp.value)
|
|
||||||
};
|
|
||||||
|
|
||||||
$(x).on('click', hdl).on('keypress', cr(hdl));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Expanding boxes on mobile
|
|
||||||
$('.Box.mobcol,.Box.fold').forEach(function(x) {
|
|
||||||
var h = x.querySelector('h2');
|
|
||||||
|
|
||||||
var hdl = function() {
|
|
||||||
$(x).toggleClass('expanded');
|
|
||||||
};
|
|
||||||
$(h).on('click', hdl).on('keypress', cr(hdl));
|
|
||||||
});
|
|
||||||
|
|
||||||
$('form').forEach(function(x) {
|
|
||||||
$(x).on('keypress', function(e) {
|
|
||||||
if ((e.keyCode == 10 || e.keyCode == 13) && e.ctrlKey) {
|
|
||||||
x.submit();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
// loader dots...
|
|
||||||
setInterval(function () {
|
|
||||||
$('.anim-dots').each(function (x) {
|
|
||||||
var $x = $(x);
|
|
||||||
var dots = $x.html() + '.';
|
|
||||||
if (dots.length == 5) dots = '.';
|
|
||||||
$x.html(dots);
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
// flipping number boxes with the mouse wheel
|
|
||||||
$('input[type=number]').on('mousewheel', function(e) {
|
|
||||||
var $this = $(this);
|
|
||||||
var val = +$this.val();
|
|
||||||
if (isNaN(val)) val = 1;
|
|
||||||
|
|
||||||
var step = +($this.attr('step') || 1);
|
|
||||||
var min = +$this.attr('min');
|
|
||||||
var max = +$this.attr('max');
|
|
||||||
if(e.wheelDelta > 0) {
|
|
||||||
val += step;
|
|
||||||
} else {
|
|
||||||
val -= step;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof min != 'undefined') val = Math.max(val, +min);
|
|
||||||
if (typeof max != 'undefined') val = Math.min(val, +max);
|
|
||||||
$this.val(val);
|
|
||||||
|
|
||||||
if ("createEvent" in document) {
|
|
||||||
var evt = document.createEvent("HTMLEvents");
|
|
||||||
evt.initEvent("change", false, true);
|
|
||||||
$this[0].dispatchEvent(evt);
|
|
||||||
} else {
|
|
||||||
$this[0].fireEvent("onchange");
|
|
||||||
}
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
var errAt = location.search.indexOf('err=');
|
|
||||||
if (errAt !== -1 && qs('.Box.errors')) {
|
|
||||||
var errs = location.search.substr(errAt+4).split(',');
|
|
||||||
var hres = [];
|
|
||||||
errs.forEach(function(er) {
|
|
||||||
var lbl = qs('label[for="'+er+'"]');
|
|
||||||
if (lbl) {
|
|
||||||
lbl.classList.add('error');
|
|
||||||
hres.push(lbl.childNodes[0].textContent.trim().replace(/: ?$/, ''));
|
|
||||||
} else {
|
|
||||||
hres.push(er);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
qs('.Box.errors .list').innerHTML = hres.join(', ');
|
|
||||||
qs('.Box.errors').classList.remove('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
Modal.init();
|
|
||||||
Notify.init();
|
|
||||||
|
|
||||||
// remove tabindixes from h2 if wide
|
|
||||||
if (window.innerWidth > 550) {
|
|
||||||
$('.Box h2').forEach(function (x) {
|
|
||||||
x.removeAttribute('tabindex');
|
|
||||||
});
|
|
||||||
|
|
||||||
// brand works as a link back to term in widescreen mode
|
|
||||||
var br = qs('#brand');
|
|
||||||
br && br.addEventListener('click', function() {
|
|
||||||
location.href='/'; // go to terminal
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$._loader = function(vis) {
|
|
||||||
$('#loader').toggleClass('show', vis);
|
|
||||||
};
|
|
||||||
|
|
||||||
function showPage() {
|
|
||||||
$('#content').addClass('load');
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ready(function() {
|
|
||||||
if (window.noAutoShow !== true) {
|
|
||||||
setTimeout(function () {
|
|
||||||
showPage();
|
|
||||||
}, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/*! http://mths.be/fromcodepoint v0.1.0 by @mathias */
|
|
||||||
if (!String.fromCodePoint) {
|
|
||||||
(function() {
|
|
||||||
var defineProperty = (function() {
|
|
||||||
// IE 8 only supports `Object.defineProperty` on DOM elements
|
|
||||||
try {
|
|
||||||
var object = {};
|
|
||||||
var $defineProperty = Object.defineProperty;
|
|
||||||
var result = $defineProperty(object, object, object) && $defineProperty;
|
|
||||||
} catch(error) {}
|
|
||||||
return result;
|
|
||||||
}());
|
|
||||||
var stringFromCharCode = String.fromCharCode;
|
|
||||||
var floor = Math.floor;
|
|
||||||
var fromCodePoint = function() {
|
|
||||||
var MAX_SIZE = 0x4000;
|
|
||||||
var codeUnits = [];
|
|
||||||
var highSurrogate;
|
|
||||||
var lowSurrogate;
|
|
||||||
var index = -1;
|
|
||||||
var length = arguments.length;
|
|
||||||
if (!length) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
var result = '';
|
|
||||||
while (++index < length) {
|
|
||||||
var codePoint = Number(arguments[index]);
|
|
||||||
if (
|
|
||||||
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
|
|
||||||
codePoint < 0 || // not a valid Unicode code point
|
|
||||||
codePoint > 0x10FFFF || // not a valid Unicode code point
|
|
||||||
floor(codePoint) != codePoint // not an integer
|
|
||||||
) {
|
|
||||||
throw RangeError('Invalid code point: ' + codePoint);
|
|
||||||
}
|
|
||||||
if (codePoint <= 0xFFFF) { // BMP code point
|
|
||||||
codeUnits.push(codePoint);
|
|
||||||
} else { // Astral code point; split in surrogate halves
|
|
||||||
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
|
||||||
codePoint -= 0x10000;
|
|
||||||
highSurrogate = (codePoint >> 10) + 0xD800;
|
|
||||||
lowSurrogate = (codePoint % 0x400) + 0xDC00;
|
|
||||||
codeUnits.push(highSurrogate, lowSurrogate);
|
|
||||||
}
|
|
||||||
if (index + 1 == length || codeUnits.length > MAX_SIZE) {
|
|
||||||
result += stringFromCharCode.apply(null, codeUnits);
|
|
||||||
codeUnits.length = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
if (defineProperty) {
|
|
||||||
defineProperty(String, 'fromCodePoint', {
|
|
||||||
'value': fromCodePoint,
|
|
||||||
'configurable': true,
|
|
||||||
'writable': true
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
String.fromCodePoint = fromCodePoint;
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
@@ -1,703 +0,0 @@
|
|||||||
/*!chibi 3.0.7, Copyright 2012-2016 Kyle Barrow, released under MIT license */
|
|
||||||
|
|
||||||
// MODIFIED VERSION.
|
|
||||||
(function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var readyfn = [],
|
|
||||||
loadedfn = [],
|
|
||||||
domready = false,
|
|
||||||
pageloaded = false,
|
|
||||||
d = document,
|
|
||||||
w = window;
|
|
||||||
|
|
||||||
// Fire any function calls on ready event
|
|
||||||
function fireReady() {
|
|
||||||
var i;
|
|
||||||
domready = true;
|
|
||||||
for (i = 0; i < readyfn.length; i += 1) {
|
|
||||||
readyfn[i]();
|
|
||||||
}
|
|
||||||
readyfn = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire any function calls on loaded event
|
|
||||||
function fireLoaded() {
|
|
||||||
var i;
|
|
||||||
pageloaded = true;
|
|
||||||
// For browsers with no DOM loaded support
|
|
||||||
if (!domready) {
|
|
||||||
fireReady();
|
|
||||||
}
|
|
||||||
for (i = 0; i < loadedfn.length; i += 1) {
|
|
||||||
loadedfn[i]();
|
|
||||||
}
|
|
||||||
loadedfn = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check DOM ready, page loaded
|
|
||||||
if (d.addEventListener) {
|
|
||||||
// Standards
|
|
||||||
d.addEventListener('DOMContentLoaded', fireReady, false);
|
|
||||||
w.addEventListener('load', fireLoaded, false);
|
|
||||||
} else if (d.attachEvent) {
|
|
||||||
// IE
|
|
||||||
d.attachEvent('onreadystatechange', fireReady);
|
|
||||||
// IE < 9
|
|
||||||
w.attachEvent('onload', fireLoaded);
|
|
||||||
} else {
|
|
||||||
// Anything else
|
|
||||||
w.onload = fireLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility functions
|
|
||||||
|
|
||||||
// Loop through node array
|
|
||||||
function nodeLoop(fn, nodes) {
|
|
||||||
var i;
|
|
||||||
// Good idea to walk up the DOM
|
|
||||||
for (i = nodes.length - 1; i >= 0; i -= 1) {
|
|
||||||
fn(nodes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to camel case
|
|
||||||
function cssCamel(property) {
|
|
||||||
return property.replace(/-\w/g, function (result) {
|
|
||||||
return result.charAt(1).toUpperCase();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get computed style
|
|
||||||
function computeStyle(elm, property) {
|
|
||||||
// IE, everything else or null
|
|
||||||
return (elm.currentStyle) ? elm.currentStyle[cssCamel(property)] : (w.getComputedStyle) ? w.getComputedStyle(elm, null).getPropertyValue(property) : null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns URI encoded query string pair
|
|
||||||
function queryPair(name, value) {
|
|
||||||
return encodeURIComponent(name).replace(/%20/g, '+') + '=' + encodeURIComponent(value).replace(/%20/g, '+');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set CSS, important to wrap in try to prevent error thown on unsupported property
|
|
||||||
function setCss(elm, property, value) {
|
|
||||||
try {
|
|
||||||
elm.style[cssCamel(property)] = value;
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show CSS
|
|
||||||
function showCss(elm) {
|
|
||||||
elm.style.display = '';
|
|
||||||
// For elements still hidden by style block
|
|
||||||
if (computeStyle(elm, 'display') === 'none') {
|
|
||||||
elm.style.display = 'block';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize form & JSON values
|
|
||||||
function serializeData(nodes) {
|
|
||||||
var querystring = '', subelm, i, j;
|
|
||||||
if (nodes.constructor === Object) { // Serialize JSON data
|
|
||||||
for (subelm in nodes) {
|
|
||||||
if (nodes.hasOwnProperty(subelm)) {
|
|
||||||
if (nodes[subelm].constructor === Array) {
|
|
||||||
for (i = 0; i < nodes[subelm].length; i += 1) {
|
|
||||||
querystring += '&' + queryPair(subelm, nodes[subelm][i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
querystring += '&' + queryPair(subelm, nodes[subelm]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // Serialize node data
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
if (elm.nodeName === 'FORM') {
|
|
||||||
for (i = 0; i < elm.elements.length; i += 1) {
|
|
||||||
subelm = elm.elements[i];
|
|
||||||
|
|
||||||
if (!subelm.disabled) {
|
|
||||||
switch (subelm.type) {
|
|
||||||
// Ignore buttons, unsupported XHR 1 form fields
|
|
||||||
case 'button':
|
|
||||||
case 'image':
|
|
||||||
case 'file':
|
|
||||||
case 'submit':
|
|
||||||
case 'reset':
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'select-one':
|
|
||||||
if (subelm.length > 0) {
|
|
||||||
querystring += '&' + queryPair(subelm.name, subelm.value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'select-multiple':
|
|
||||||
for (j = 0; j < subelm.length; j += 1) {
|
|
||||||
if (subelm[j].selected) {
|
|
||||||
querystring += '&' + queryPair(subelm.name, subelm[j].value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'checkbox':
|
|
||||||
case 'radio':
|
|
||||||
if (subelm.checked) {
|
|
||||||
querystring += '&' + queryPair(subelm.name, subelm.value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Everything else including shinny new HTML5 input types
|
|
||||||
default:
|
|
||||||
querystring += '&' + queryPair(subelm.name, subelm.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, nodes);
|
|
||||||
}
|
|
||||||
// Tidy up first &
|
|
||||||
return (querystring.length > 0) ? querystring.substring(1) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Class helper
|
|
||||||
function classHelper(classes, action, nodes) {
|
|
||||||
var classarray, search, i, replace, has = false;
|
|
||||||
if (classes) {
|
|
||||||
// Trim any whitespace
|
|
||||||
classarray = classes.split(/\s+/);
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
for (i = 0; i < classarray.length; i += 1) {
|
|
||||||
var clz = classarray[i];
|
|
||||||
if (action === 'remove') {
|
|
||||||
elm.classList.remove(clz);
|
|
||||||
}
|
|
||||||
else if (action === 'add') {
|
|
||||||
elm.classList.add(clz);
|
|
||||||
}
|
|
||||||
else if (action === 'toggle') {
|
|
||||||
elm.classList.toggle(clz);
|
|
||||||
}
|
|
||||||
else if (action === 'has') {
|
|
||||||
if (elm.classList.contains(clz)) {
|
|
||||||
has = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// search = new RegExp('\\b' + classarray[i] + '\\b', 'g');
|
|
||||||
// replace = new RegExp(' *' + classarray[i] + '\\b', 'g');
|
|
||||||
// if (action === 'remove') {
|
|
||||||
// elm.className = elm.className.replace(search, '');
|
|
||||||
// } else if (action === 'toggle') {
|
|
||||||
// elm.className = (elm.className.match(search)) ? elm.className.replace(replace, '') : elm.className + ' ' + classarray[i];
|
|
||||||
// } else if (action === 'has') {
|
|
||||||
// if (elm.className.match(search)) {
|
|
||||||
// has = true;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}, nodes);
|
|
||||||
}
|
|
||||||
return has;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTML insertion helper
|
|
||||||
function insertHtml(value, position, nodes) {
|
|
||||||
var tmpnodes, tmpnode;
|
|
||||||
if (value) {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
// No insertAdjacentHTML support for FF < 8 and IE doesn't allow insertAdjacentHTML table manipulation, so use this instead
|
|
||||||
// Convert string to node. We can't innerHTML on a document fragment
|
|
||||||
tmpnodes = d.createElement('div');
|
|
||||||
tmpnodes.innerHTML = value;
|
|
||||||
while ((tmpnode = tmpnodes.lastChild) !== null) {
|
|
||||||
// Catch error in unlikely case elm has been removed
|
|
||||||
try {
|
|
||||||
if (position === 'before') {
|
|
||||||
elm.parentNode.insertBefore(tmpnode, elm);
|
|
||||||
} else if (position === 'after') {
|
|
||||||
elm.parentNode.insertBefore(tmpnode, elm.nextSibling);
|
|
||||||
} else if (position === 'append') {
|
|
||||||
elm.appendChild(tmpnode);
|
|
||||||
} else if (position === 'prepend') {
|
|
||||||
elm.insertBefore(tmpnode, elm.firstChild);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, nodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get nodes and return chibi
|
|
||||||
function chibi(selector) {
|
|
||||||
var cb, nodes = [], json = false, nodelist, i;
|
|
||||||
|
|
||||||
if (selector) {
|
|
||||||
|
|
||||||
// Element node, would prefer to use (selector instanceof HTMLElement) but no IE support
|
|
||||||
if (selector.nodeType && selector.nodeType === 1) {
|
|
||||||
nodes = [selector]; // return element as node list
|
|
||||||
} else if (typeof selector === 'object') {
|
|
||||||
// JSON, document object or node list, would prefer to use (selector instanceof NodeList) but no IE support
|
|
||||||
json = (typeof selector.length !== 'number');
|
|
||||||
nodes = selector;
|
|
||||||
} else if (typeof selector === 'string') {
|
|
||||||
nodelist = d.querySelectorAll(selector);
|
|
||||||
|
|
||||||
// Convert node list to array so results have full access to array methods
|
|
||||||
// Array.prototype.slice.call not supported in IE < 9 and often slower than loop anyway
|
|
||||||
for (i = 0; i < nodelist.length; i += 1) {
|
|
||||||
nodes[i] = nodelist[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only attach nodes if not JSON
|
|
||||||
cb = json ? {} : nodes;
|
|
||||||
|
|
||||||
// Public functions
|
|
||||||
|
|
||||||
// Executes a function on nodes
|
|
||||||
cb.each = function (fn) {
|
|
||||||
if (typeof fn === 'function') {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
// <= IE 8 loses scope so need to apply
|
|
||||||
return fn.apply(elm, arguments);
|
|
||||||
}, nodes);
|
|
||||||
}
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Find first
|
|
||||||
cb.first = function () {
|
|
||||||
return chibi(nodes.shift());
|
|
||||||
};
|
|
||||||
// Find last
|
|
||||||
cb.last = function () {
|
|
||||||
return chibi(nodes.pop());
|
|
||||||
};
|
|
||||||
// Find odd
|
|
||||||
cb.odd = function () {
|
|
||||||
var odds = [], i;
|
|
||||||
for (i = 0; i < nodes.length; i += 2) {
|
|
||||||
odds.push(nodes[i]);
|
|
||||||
}
|
|
||||||
return chibi(odds);
|
|
||||||
};
|
|
||||||
// Find even
|
|
||||||
cb.even = function () {
|
|
||||||
var evens = [], i;
|
|
||||||
for (i = 1; i < nodes.length; i += 2) {
|
|
||||||
evens.push(nodes[i]);
|
|
||||||
}
|
|
||||||
return chibi(evens);
|
|
||||||
};
|
|
||||||
// Hide node
|
|
||||||
cb.hide = function () {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
elm.style.display = 'none';
|
|
||||||
}, nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Show node
|
|
||||||
cb.show = function () {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
showCss(elm);
|
|
||||||
}, nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Toggle node display
|
|
||||||
cb.toggle = function (state) {
|
|
||||||
if (typeof state != 'undefined') { // ADDED
|
|
||||||
if (state)
|
|
||||||
cb.show();
|
|
||||||
else
|
|
||||||
cb.hide();
|
|
||||||
} else {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
// computeStyle instead of style.display == 'none' catches elements that are hidden via style block
|
|
||||||
if (computeStyle(elm, 'display') === 'none') {
|
|
||||||
showCss(elm);
|
|
||||||
} else {
|
|
||||||
elm.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
}, nodes);
|
|
||||||
}
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Remove node
|
|
||||||
cb.remove = function () {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
// Catch error in unlikely case elm has been removed
|
|
||||||
try {
|
|
||||||
elm.parentNode.removeChild(elm);
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
}, nodes);
|
|
||||||
return chibi();
|
|
||||||
};
|
|
||||||
// Get/Set CSS
|
|
||||||
cb.css = function (property, value) {
|
|
||||||
if (property) {
|
|
||||||
if (value || value === '') {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
setCss(elm, property, value);
|
|
||||||
}, nodes);
|
|
||||||
return cb;
|
|
||||||
}
|
|
||||||
if (nodes[0]) {
|
|
||||||
if (nodes[0].style[cssCamel(property)]) {
|
|
||||||
return nodes[0].style[cssCamel(property)];
|
|
||||||
}
|
|
||||||
if (computeStyle(nodes[0], property)) {
|
|
||||||
return computeStyle(nodes[0], property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Get class(es)
|
|
||||||
cb.getClass = function () {
|
|
||||||
if (nodes[0] && nodes[0].className.length > 0) {
|
|
||||||
// Weak IE trim support
|
|
||||||
return nodes[0].className.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '').replace(/\s+/, ' ');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Set (replaces) classes
|
|
||||||
cb.setClass = function (classes) {
|
|
||||||
if (classes || classes === '') {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
elm.className = classes;
|
|
||||||
}, nodes);
|
|
||||||
}
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Add class
|
|
||||||
cb.addClass = function (classes) {
|
|
||||||
classHelper(classes, 'add', nodes);
|
|
||||||
// if (classes) {
|
|
||||||
// nodeLoop(function (elm) {
|
|
||||||
// elm.className += ' ' + classes;
|
|
||||||
// }, nodes);
|
|
||||||
// }
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Remove class
|
|
||||||
cb.removeClass = function (classes) {
|
|
||||||
classHelper(classes, 'remove', nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Toggle class
|
|
||||||
cb.toggleClass = function (classes, set) {
|
|
||||||
var method = ((typeof set === 'undefined') ? 'toggle' : (+set ? 'add' : 'remove'));
|
|
||||||
classHelper(classes, method, nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Has class
|
|
||||||
cb.hasClass = function (classes) {
|
|
||||||
return classHelper(classes, 'has', nodes);
|
|
||||||
};
|
|
||||||
// Get/set HTML
|
|
||||||
cb.html = function (value) {
|
|
||||||
if (value || value === '') {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
elm.innerHTML = value;
|
|
||||||
}, nodes);
|
|
||||||
return cb;
|
|
||||||
}
|
|
||||||
if (nodes[0]) {
|
|
||||||
return nodes[0].innerHTML;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Insert HTML before selector
|
|
||||||
cb.htmlBefore = function (value) {
|
|
||||||
insertHtml(value, 'before', nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Insert HTML after selector
|
|
||||||
cb.htmlAfter = function (value) {
|
|
||||||
insertHtml(value, 'after', nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Insert HTML after selector innerHTML
|
|
||||||
cb.htmlAppend = function (value) {
|
|
||||||
insertHtml(value, 'append', nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Insert HTML before selector innerHTML
|
|
||||||
cb.htmlPrepend = function (value) {
|
|
||||||
insertHtml(value, 'prepend', nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Get/Set HTML attributes
|
|
||||||
cb.attr = function (property, value) {
|
|
||||||
if (property) {
|
|
||||||
property = property.toLowerCase();
|
|
||||||
// IE < 9 doesn't allow style or class via get/setAttribute so switch. cssText returns prettier CSS anyway
|
|
||||||
if (typeof value !== 'undefined') {//FIXED BUG HERE
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
if (property === 'style') {
|
|
||||||
elm.style.cssText = value;
|
|
||||||
} else if (property === 'class') {
|
|
||||||
elm.className = value;
|
|
||||||
} else {
|
|
||||||
elm.setAttribute(property, value);
|
|
||||||
}
|
|
||||||
}, nodes);
|
|
||||||
return cb;
|
|
||||||
}
|
|
||||||
if (nodes[0]) {
|
|
||||||
if (property === 'style') {
|
|
||||||
if (nodes[0].style.cssText) {
|
|
||||||
return nodes[0].style.cssText;
|
|
||||||
}
|
|
||||||
} else if (property === 'class') {
|
|
||||||
if (nodes[0].className) {
|
|
||||||
return nodes[0].className;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (nodes[0].getAttribute(property)) {
|
|
||||||
return nodes[0].getAttribute(property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Get/Set HTML data property
|
|
||||||
cb.data = function (key, value) {
|
|
||||||
if (key) {
|
|
||||||
return cb.attr('data-' + key, value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Get/Set form element values
|
|
||||||
cb.val = function (value) {
|
|
||||||
var values, i, j;
|
|
||||||
if (typeof value != 'undefined') { // FIXED A BUG HERE
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
switch (elm.nodeName) {
|
|
||||||
case 'SELECT':
|
|
||||||
if (typeof value === 'string' || typeof value === 'number') {
|
|
||||||
value = [value];
|
|
||||||
}
|
|
||||||
for (i = 0; i < elm.length; i += 1) {
|
|
||||||
// Multiple select
|
|
||||||
for (j = 0; j < value.length; j += 1) {
|
|
||||||
elm[i].selected = '';
|
|
||||||
if (elm[i].value === ""+value[j]) {
|
|
||||||
elm[i].selected = 'selected';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'INPUT':
|
|
||||||
case 'TEXTAREA':
|
|
||||||
case 'BUTTON':
|
|
||||||
elm.value = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}, nodes);
|
|
||||||
|
|
||||||
return cb;
|
|
||||||
}
|
|
||||||
if (nodes[0]) {
|
|
||||||
switch (nodes[0].nodeName) {
|
|
||||||
case 'SELECT':
|
|
||||||
values = [];
|
|
||||||
for (i = 0; i < nodes[0].length; i += 1) {
|
|
||||||
if (nodes[0][i].selected) {
|
|
||||||
values.push(nodes[0][i].value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (values.length > 1) ? values : values[0];
|
|
||||||
case 'INPUT':
|
|
||||||
case 'TEXTAREA':
|
|
||||||
case 'BUTTON':
|
|
||||||
return nodes[0].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Return matching checked checkbox or radios
|
|
||||||
cb.checked = function (check) {
|
|
||||||
if (typeof check === 'boolean') {
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
if (elm.nodeName === 'INPUT' && (elm.type === 'checkbox' || elm.type === 'radio')) {
|
|
||||||
elm.checked = check;
|
|
||||||
}
|
|
||||||
}, nodes);
|
|
||||||
return cb;
|
|
||||||
}
|
|
||||||
if (nodes[0] && nodes[0].nodeName === 'INPUT' && (nodes[0].type === 'checkbox' || nodes[0].type === 'radio')) {
|
|
||||||
return (!!nodes[0].checked);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Add event handler
|
|
||||||
cb.on = function (event, fn) {
|
|
||||||
if (selector === w || selector === d) {
|
|
||||||
nodes = [selector];
|
|
||||||
}
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
if (d.addEventListener) {
|
|
||||||
elm.addEventListener(event, fn, false);
|
|
||||||
} else if (d.attachEvent) {
|
|
||||||
// <= IE 8 loses scope so need to apply, we add this to object so we can detach later (can't detach anonymous functions)
|
|
||||||
elm[event + fn] = function () {
|
|
||||||
return fn.apply(elm, arguments);
|
|
||||||
};
|
|
||||||
elm.attachEvent('on' + event, elm[event + fn]);
|
|
||||||
}
|
|
||||||
}, nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
// Remove event handler
|
|
||||||
cb.off = function (event, fn) {
|
|
||||||
if (selector === w || selector === d) {
|
|
||||||
nodes = [selector];
|
|
||||||
}
|
|
||||||
nodeLoop(function (elm) {
|
|
||||||
if (d.addEventListener) {
|
|
||||||
elm.removeEventListener(event, fn, false);
|
|
||||||
} else if (d.attachEvent) {
|
|
||||||
elm.detachEvent('on' + event, elm[event + fn]);
|
|
||||||
// Tidy up
|
|
||||||
elm[event + fn] = null;
|
|
||||||
}
|
|
||||||
}, nodes);
|
|
||||||
return cb;
|
|
||||||
};
|
|
||||||
return cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic XHR
|
|
||||||
chibi.ajax = function (options) { // if options is a number, it's timeout in ms
|
|
||||||
var opts = extend({
|
|
||||||
method: 'GET',
|
|
||||||
nocache: true,
|
|
||||||
timeout: 5000,
|
|
||||||
loader: true,
|
|
||||||
callback: null
|
|
||||||
}, options);
|
|
||||||
opts.method = opts.method.toUpperCase();
|
|
||||||
|
|
||||||
var loaderFn = opts.loader ? chibi._loader : function(){};
|
|
||||||
var url = opts.url;
|
|
||||||
var method = opts.method;
|
|
||||||
var query = null;
|
|
||||||
|
|
||||||
if (opts.data) {
|
|
||||||
query = serializeData(opts.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query && (method === 'GET')) {
|
|
||||||
url += (url.indexOf('?') === -1) ? '?' + query : '&' + query;
|
|
||||||
query = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
|
|
||||||
// prevent caching
|
|
||||||
if (opts.nocache) {
|
|
||||||
var ts = (+(new Date())).toString(36);
|
|
||||||
url += ((url.indexOf('?') === -1) ? '?' : '&') + '_=' + ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
loaderFn(true);
|
|
||||||
|
|
||||||
xhr.open(method, url, true);
|
|
||||||
xhr.timeout = opts.timeout;
|
|
||||||
|
|
||||||
// Abort after given timeout
|
|
||||||
var abortTmeo = setTimeout(function () {
|
|
||||||
console.error("XHR timed out.");
|
|
||||||
xhr.abort();
|
|
||||||
loaderFn(false);
|
|
||||||
}, opts.timeout + 10);
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
|
||||||
if (xhr.readyState === 4) {
|
|
||||||
loaderFn(false);
|
|
||||||
|
|
||||||
opts.callback && opts.callback(xhr.responseText, xhr.status);
|
|
||||||
|
|
||||||
clearTimeout(abortTmeo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
|
||||||
if (method === 'POST') {
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send(query);
|
|
||||||
return xhr;
|
|
||||||
};
|
|
||||||
|
|
||||||
chibi._loader = function(){};
|
|
||||||
|
|
||||||
// Alias to cb.ajax(url, 'get', callback)
|
|
||||||
chibi.get = function (url, callback, opts) {
|
|
||||||
opts = opts || {};
|
|
||||||
opts.url = url;
|
|
||||||
opts.callback = callback;
|
|
||||||
opts.method = 'GET';
|
|
||||||
return chibi.ajax(opts);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Alias to cb.ajax(url, 'post', callback)
|
|
||||||
chibi.post = function (url, callback, opts) {
|
|
||||||
opts = opts || {};
|
|
||||||
opts.url = url;
|
|
||||||
opts.callback = callback;
|
|
||||||
opts.method = 'POST';
|
|
||||||
return chibi.ajax(opts);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fire on DOM ready
|
|
||||||
chibi.ready = function (fn) {
|
|
||||||
if (fn) {
|
|
||||||
if (domready) {
|
|
||||||
fn();
|
|
||||||
return chibi;
|
|
||||||
} else {
|
|
||||||
readyfn.push(fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fire on page loaded
|
|
||||||
chibi.loaded = function (fn) {
|
|
||||||
if (fn) {
|
|
||||||
if (pageloaded) {
|
|
||||||
fn();
|
|
||||||
return chibi;
|
|
||||||
} else {
|
|
||||||
loadedfn.push(fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var entityMap = {
|
|
||||||
'&': '&',
|
|
||||||
'<': '<',
|
|
||||||
'>': '>',
|
|
||||||
'"': '"',
|
|
||||||
"'": ''',
|
|
||||||
'/': '/',
|
|
||||||
'`': '`',
|
|
||||||
'=': '='
|
|
||||||
};
|
|
||||||
|
|
||||||
chibi.htmlEscape = function(string) {
|
|
||||||
return String(string).replace(/[&<>"'`=\/]/g, function (s) {
|
|
||||||
return entityMap[s];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set Chibi's global namespace here ($)
|
|
||||||
w.$ = chibi;
|
|
||||||
}());
|
|
||||||
@@ -1,310 +0,0 @@
|
|||||||
// keymaster.js
|
|
||||||
// (c) 2011-2013 Thomas Fuchs
|
|
||||||
// keymaster.js may be freely distributed under the MIT license.
|
|
||||||
|
|
||||||
;(function(global){
|
|
||||||
var k,
|
|
||||||
_handlers = {},
|
|
||||||
_mods = { 16: false, 18: false, 17: false, 91: false },
|
|
||||||
_scope = 'all',
|
|
||||||
// modifier keys
|
|
||||||
_MODIFIERS = {
|
|
||||||
'⇧': 16, shift: 16,
|
|
||||||
'⌥': 18, alt: 18, option: 18,
|
|
||||||
'⌃': 17, ctrl: 17, control: 17,
|
|
||||||
'⌘': 91, command: 91
|
|
||||||
},
|
|
||||||
// special keys
|
|
||||||
_MAP = {
|
|
||||||
backspace: 8, tab: 9, clear: 12,
|
|
||||||
enter: 13, 'return': 13,
|
|
||||||
esc: 27, escape: 27, space: 32,
|
|
||||||
left: 37, up: 38,
|
|
||||||
right: 39, down: 40,
|
|
||||||
del: 46, 'delete': 46,
|
|
||||||
home: 36, end: 35,
|
|
||||||
pageup: 33, pagedown: 34,
|
|
||||||
',': 188, '.': 190, '/': 191,
|
|
||||||
'`': 192, '-': 189, '=': 187,
|
|
||||||
';': 186, '\'': 222,
|
|
||||||
'[': 219, ']': 221, '\\': 220,
|
|
||||||
// added:
|
|
||||||
insert: 45,
|
|
||||||
np_0: 96, np_1: 97, np_2: 98, np_3: 99, np_4: 100, np_5: 101,
|
|
||||||
np_6: 102, np_7: 103, np_8: 104, np_9: 105, np_mul: 106,
|
|
||||||
np_add: 107, np_sub: 109, np_point: 110, np_div: 111, numlock: 144,
|
|
||||||
},
|
|
||||||
code = function(x){
|
|
||||||
return _MAP[x] || x.toUpperCase().charCodeAt(0);
|
|
||||||
},
|
|
||||||
_downKeys = [];
|
|
||||||
|
|
||||||
for(k=1;k<20;k++) _MAP['f'+k] = 111+k;
|
|
||||||
|
|
||||||
// IE doesn't support Array#indexOf, so have a simple replacement
|
|
||||||
function index(array, item){
|
|
||||||
var i = array.length;
|
|
||||||
while(i--) if(array[i]===item) return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for comparing mods before unassignment
|
|
||||||
function compareArray(a1, a2) {
|
|
||||||
if (a1.length != a2.length) return false;
|
|
||||||
for (var i = 0; i < a1.length; i++) {
|
|
||||||
if (a1[i] !== a2[i]) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var modifierMap = {
|
|
||||||
16:'shiftKey',
|
|
||||||
18:'altKey',
|
|
||||||
17:'ctrlKey',
|
|
||||||
91:'metaKey'
|
|
||||||
};
|
|
||||||
function updateModifierKey(event) {
|
|
||||||
for(k in _mods) _mods[k] = event[modifierMap[k]];
|
|
||||||
};
|
|
||||||
|
|
||||||
function isModifierPressed(mod) {
|
|
||||||
if (mod=='control'||mod=='ctrl') return _mods[17];
|
|
||||||
if (mod=='shift') return _mods[16];
|
|
||||||
if (mod=='meta') return _mods[91];
|
|
||||||
if (mod=='alt') return _mods[18];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle keydown event
|
|
||||||
function dispatch(event) {
|
|
||||||
var key, handler, k, i, modifiersMatch, scope;
|
|
||||||
key = event.keyCode;
|
|
||||||
|
|
||||||
if (index(_downKeys, key) == -1) {
|
|
||||||
_downKeys.push(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a modifier key, set the key.<modifierkeyname> property to true and return
|
|
||||||
if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko
|
|
||||||
if(key in _mods) {
|
|
||||||
_mods[key] = true;
|
|
||||||
// 'assignKey' from inside this closure is exported to window.key
|
|
||||||
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateModifierKey(event);
|
|
||||||
|
|
||||||
// see if we need to ignore the keypress (filter() can can be overridden)
|
|
||||||
// by default ignore key presses if a select, textarea, or input is focused
|
|
||||||
if(!assignKey.filter.call(this, event)) return;
|
|
||||||
|
|
||||||
// abort if no potentially matching shortcuts found
|
|
||||||
if (!(key in _handlers)) return;
|
|
||||||
|
|
||||||
scope = getScope();
|
|
||||||
|
|
||||||
// for each potential shortcut
|
|
||||||
for (i = 0; i < _handlers[key].length; i++) {
|
|
||||||
handler = _handlers[key][i];
|
|
||||||
|
|
||||||
// see if it's in the current scope
|
|
||||||
if(handler.scope == scope || handler.scope == 'all'){
|
|
||||||
// check if modifiers match if any
|
|
||||||
modifiersMatch = handler.mods.length > 0;
|
|
||||||
for(k in _mods)
|
|
||||||
if((!_mods[k] && index(handler.mods, +k) > -1) ||
|
|
||||||
(_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false;
|
|
||||||
// call the handler and stop the event if neccessary
|
|
||||||
if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){
|
|
||||||
if(handler.method(event, handler)===false){
|
|
||||||
if(event.preventDefault) event.preventDefault();
|
|
||||||
else event.returnValue = false;
|
|
||||||
if(event.stopPropagation) event.stopPropagation();
|
|
||||||
if(event.cancelBubble) event.cancelBubble = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// unset modifier keys on keyup
|
|
||||||
function clearModifier(event){
|
|
||||||
var key = event.keyCode, k,
|
|
||||||
i = index(_downKeys, key);
|
|
||||||
|
|
||||||
// remove key from _downKeys
|
|
||||||
if (i >= 0) {
|
|
||||||
_downKeys.splice(i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(key == 93 || key == 224) key = 91;
|
|
||||||
if(key in _mods) {
|
|
||||||
_mods[key] = false;
|
|
||||||
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function resetModifiers() {
|
|
||||||
for(k in _mods) _mods[k] = false;
|
|
||||||
for(k in _MODIFIERS) assignKey[k] = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// parse and assign shortcut
|
|
||||||
function assignKey(key, scope, method){
|
|
||||||
var keys, mods;
|
|
||||||
keys = getKeys(key);
|
|
||||||
if (method === undefined) {
|
|
||||||
method = scope;
|
|
||||||
scope = 'all';
|
|
||||||
}
|
|
||||||
|
|
||||||
// for each shortcut
|
|
||||||
for (var i = 0; i < keys.length; i++) {
|
|
||||||
// set modifier keys if any
|
|
||||||
mods = [];
|
|
||||||
key = keys[i].split('+');
|
|
||||||
if (key.length > 1){
|
|
||||||
mods = getMods(key);
|
|
||||||
key = [key[key.length-1]];
|
|
||||||
}
|
|
||||||
// convert to keycode and...
|
|
||||||
key = key[0]
|
|
||||||
key = code(key);
|
|
||||||
// ...store handler
|
|
||||||
if (!(key in _handlers)) _handlers[key] = [];
|
|
||||||
_handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// unbind all handlers for given key in current scope
|
|
||||||
function unbindKey(key, scope) {
|
|
||||||
var multipleKeys, keys,
|
|
||||||
mods = [],
|
|
||||||
i, j, obj;
|
|
||||||
|
|
||||||
multipleKeys = getKeys(key);
|
|
||||||
|
|
||||||
for (j = 0; j < multipleKeys.length; j++) {
|
|
||||||
keys = multipleKeys[j].split('+');
|
|
||||||
|
|
||||||
if (keys.length > 1) {
|
|
||||||
mods = getMods(keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
key = keys[keys.length - 1];
|
|
||||||
key = code(key);
|
|
||||||
|
|
||||||
if (scope === undefined) {
|
|
||||||
scope = getScope();
|
|
||||||
}
|
|
||||||
if (!_handlers[key]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (i = 0; i < _handlers[key].length; i++) {
|
|
||||||
obj = _handlers[key][i];
|
|
||||||
// only clear handlers if correct scope and mods match
|
|
||||||
if (obj.scope === scope && compareArray(obj.mods, mods)) {
|
|
||||||
_handlers[key][i] = {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns true if the key with code 'keyCode' is currently down
|
|
||||||
// Converts strings into key codes.
|
|
||||||
function isPressed(keyCode) {
|
|
||||||
if (typeof(keyCode)=='string') {
|
|
||||||
keyCode = code(keyCode);
|
|
||||||
}
|
|
||||||
return index(_downKeys, keyCode) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPressedKeyCodes() {
|
|
||||||
return _downKeys.slice(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filter(event){
|
|
||||||
var tagName = (event.target || event.srcElement).tagName;
|
|
||||||
// ignore keypressed in any elements that support keyboard data input
|
|
||||||
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize key.<modifier> to false
|
|
||||||
for(k in _MODIFIERS) assignKey[k] = false;
|
|
||||||
|
|
||||||
// set current scope (default 'all')
|
|
||||||
function setScope(scope){ _scope = scope || 'all' };
|
|
||||||
function getScope(){ return _scope || 'all' };
|
|
||||||
|
|
||||||
// delete all handlers for a given scope
|
|
||||||
function deleteScope(scope){
|
|
||||||
var key, handlers, i;
|
|
||||||
|
|
||||||
for (key in _handlers) {
|
|
||||||
handlers = _handlers[key];
|
|
||||||
for (i = 0; i < handlers.length; ) {
|
|
||||||
if (handlers[i].scope === scope) handlers.splice(i, 1);
|
|
||||||
else i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// abstract key logic for assign and unassign
|
|
||||||
function getKeys(key) {
|
|
||||||
var keys;
|
|
||||||
key = key.replace(/\s/g, '');
|
|
||||||
keys = key.split(',');
|
|
||||||
if ((keys[keys.length - 1]) == '') {
|
|
||||||
keys[keys.length - 2] += ',';
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
// abstract mods logic for assign and unassign
|
|
||||||
function getMods(key) {
|
|
||||||
var mods = key.slice(0, key.length - 1);
|
|
||||||
for (var mi = 0; mi < mods.length; mi++)
|
|
||||||
mods[mi] = _MODIFIERS[mods[mi]];
|
|
||||||
return mods;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cross-browser events
|
|
||||||
function addEvent(object, event, method) {
|
|
||||||
if (object.addEventListener)
|
|
||||||
object.addEventListener(event, method, false);
|
|
||||||
else if(object.attachEvent)
|
|
||||||
object.attachEvent('on'+event, function(){ method(window.event) });
|
|
||||||
};
|
|
||||||
|
|
||||||
// set the handlers globally on document
|
|
||||||
addEvent(document, 'keydown', function(event) { dispatch(event) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48
|
|
||||||
addEvent(document, 'keyup', clearModifier);
|
|
||||||
|
|
||||||
// reset modifiers to false whenever the window is (re)focused.
|
|
||||||
addEvent(window, 'focus', resetModifiers);
|
|
||||||
|
|
||||||
// store previously defined key
|
|
||||||
var previousKey = global.key;
|
|
||||||
|
|
||||||
// restore previously defined key and return reference to our key object
|
|
||||||
function noConflict() {
|
|
||||||
var k = global.key;
|
|
||||||
global.key = previousKey;
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set window.key and window.key.set/get/deleteScope, and the default filter
|
|
||||||
global.key = assignKey;
|
|
||||||
global.key.setScope = setScope;
|
|
||||||
global.key.getScope = getScope;
|
|
||||||
global.key.deleteScope = deleteScope;
|
|
||||||
global.key.filter = filter;
|
|
||||||
global.key.isPressed = isPressed;
|
|
||||||
global.key.isModifier = isModifierPressed;
|
|
||||||
global.key.getPressedKeyCodes = getPressedKeyCodes;
|
|
||||||
global.key.noConflict = noConflict;
|
|
||||||
global.key.unbind = unbindKey;
|
|
||||||
|
|
||||||
if(typeof module !== 'undefined') module.exports = assignKey;
|
|
||||||
|
|
||||||
})(this);
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// Generated from PHP locale file
|
|
||||||
var _tr = {
|
|
||||||
"wifi.connected_ip_is": "Connected, IP is ",
|
|
||||||
"wifi.not_conn": "Not connected.",
|
|
||||||
"wifi.enter_passwd": "Enter password for \":ssid:\""
|
|
||||||
};
|
|
||||||
|
|
||||||
function tr(key) { return _tr[key] || '?'+key+'?'; }
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/** Module for toggling a modal overlay */
|
|
||||||
(function () {
|
|
||||||
var modal = {};
|
|
||||||
var curCloseCb = null;
|
|
||||||
|
|
||||||
modal.show = function (sel, closeCb) {
|
|
||||||
var $m = $(sel);
|
|
||||||
$m.removeClass('hidden visible');
|
|
||||||
setTimeout(function () {
|
|
||||||
$m.addClass('visible');
|
|
||||||
}, 1);
|
|
||||||
curCloseCb = closeCb;
|
|
||||||
};
|
|
||||||
|
|
||||||
modal.hide = function (sel) {
|
|
||||||
var $m = $(sel);
|
|
||||||
$m.removeClass('visible');
|
|
||||||
setTimeout(function () {
|
|
||||||
$m.addClass('hidden');
|
|
||||||
if (curCloseCb) curCloseCb();
|
|
||||||
}, 500); // transition time
|
|
||||||
};
|
|
||||||
|
|
||||||
modal.init = function () {
|
|
||||||
// close modal by click outside the dialog
|
|
||||||
$('.Modal').on('click', function () {
|
|
||||||
if ($(this).hasClass('no-close')) return; // this is a no-close modal
|
|
||||||
modal.hide(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.Dialog').on('click', function (e) {
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Hide all modals on esc
|
|
||||||
$(window).on('keydown', function (e) {
|
|
||||||
if (e.which == 27) {
|
|
||||||
modal.hide('.Modal');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
window.Modal = modal;
|
|
||||||
})();
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
(function (nt) {
|
|
||||||
var sel = '#notif';
|
|
||||||
|
|
||||||
var hideTmeo1; // timeout to start hiding (transition)
|
|
||||||
var hideTmeo2; // timeout to add the hidden class
|
|
||||||
|
|
||||||
nt.show = function (message, timeout) {
|
|
||||||
$(sel).html(message);
|
|
||||||
Modal.show(sel);
|
|
||||||
|
|
||||||
clearTimeout(hideTmeo1);
|
|
||||||
clearTimeout(hideTmeo2);
|
|
||||||
|
|
||||||
if (undef(timeout)) timeout = 2500;
|
|
||||||
|
|
||||||
hideTmeo1 = setTimeout(nt.hide, timeout);
|
|
||||||
};
|
|
||||||
|
|
||||||
nt.hide = function () {
|
|
||||||
var $m = $(sel);
|
|
||||||
$m.removeClass('visible');
|
|
||||||
hideTmeo2 = setTimeout(function () {
|
|
||||||
$m.addClass('hidden');
|
|
||||||
}, 250); // transition time
|
|
||||||
};
|
|
||||||
|
|
||||||
nt.init = function() {
|
|
||||||
$(sel).on('click', function() {
|
|
||||||
nt.hide(this);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
})(window.Notify = {});
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
/** Init the terminal sub-module - called from HTML */
|
|
||||||
window.termInit = function () {
|
|
||||||
Conn.init();
|
|
||||||
Input.init();
|
|
||||||
TermUpl.init();
|
|
||||||
};
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
/** Handle connections */
|
|
||||||
var Conn = (function() {
|
|
||||||
var ws;
|
|
||||||
var heartbeatTout;
|
|
||||||
var pingIv;
|
|
||||||
var xoff = false;
|
|
||||||
var autoXoffTout;
|
|
||||||
|
|
||||||
function onOpen(evt) {
|
|
||||||
console.log("CONNECTED");
|
|
||||||
}
|
|
||||||
|
|
||||||
function onClose(evt) {
|
|
||||||
console.warn("SOCKET CLOSED, code "+evt.code+". Reconnecting...");
|
|
||||||
setTimeout(function() {
|
|
||||||
init();
|
|
||||||
}, 200);
|
|
||||||
// this happens when the buffer gets fucked up via invalid unicode.
|
|
||||||
// we basically use polling instead of socket then
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMessage(evt) {
|
|
||||||
try {
|
|
||||||
// . = heartbeat
|
|
||||||
switch (evt.data.charAt(0)) {
|
|
||||||
case 'B':
|
|
||||||
case 'T':
|
|
||||||
case 'S':
|
|
||||||
Screen.load(evt.data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '-':
|
|
||||||
//console.log('xoff');
|
|
||||||
xoff = true;
|
|
||||||
autoXoffTout = setTimeout(function(){xoff=false;}, 250);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '+':
|
|
||||||
//console.log('xon');
|
|
||||||
xoff = false;
|
|
||||||
clearTimeout(autoXoffTout);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
heartbeat();
|
|
||||||
} catch(e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function canSend() {
|
|
||||||
return !xoff;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doSend(message) {
|
|
||||||
if (_demo) {
|
|
||||||
console.log("TX: ", message);
|
|
||||||
return true; // Simulate success
|
|
||||||
}
|
|
||||||
if (xoff) {
|
|
||||||
// TODO queue
|
|
||||||
console.log("Can't send, flood control.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ws) return false; // for dry testing
|
|
||||||
if (ws.readyState != 1) {
|
|
||||||
console.error("Socket not ready");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (typeof message != "string") {
|
|
||||||
message = JSON.stringify(message);
|
|
||||||
}
|
|
||||||
ws.send(message);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
if (_demo) {
|
|
||||||
console.log("Demo mode!");
|
|
||||||
Screen.load(_demo_screen);
|
|
||||||
showPage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
heartbeat();
|
|
||||||
|
|
||||||
ws = new WebSocket("ws://"+_root+"/term/update.ws");
|
|
||||||
ws.onopen = onOpen;
|
|
||||||
ws.onclose = onClose;
|
|
||||||
ws.onmessage = onMessage;
|
|
||||||
|
|
||||||
console.log("Opening socket.");
|
|
||||||
|
|
||||||
// Ask for initial data
|
|
||||||
$.get('http://'+_root+'/term/init', function(resp, status) {
|
|
||||||
if (status !== 200) location.reload(true);
|
|
||||||
console.log("Data received!");
|
|
||||||
Screen.load(resp);
|
|
||||||
heartbeat();
|
|
||||||
|
|
||||||
showPage();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function heartbeat() {
|
|
||||||
clearTimeout(heartbeatTout);
|
|
||||||
heartbeatTout = setTimeout(heartbeatFail, 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function heartbeatFail() {
|
|
||||||
console.error("Heartbeat lost, probing server...");
|
|
||||||
pingIv = setInterval(function() {
|
|
||||||
console.log("> ping");
|
|
||||||
$.get('http://'+_root+'/system/ping', function(resp, status) {
|
|
||||||
if (status == 200) {
|
|
||||||
clearInterval(pingIv);
|
|
||||||
console.info("Server ready, reloading page...");
|
|
||||||
location.reload();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
timeout: 100,
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
ws: null,
|
|
||||||
init: init,
|
|
||||||
send: doSend,
|
|
||||||
canSend: canSend, // check flood control
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
/**
|
|
||||||
* User input
|
|
||||||
*
|
|
||||||
* --- Rx messages: ---
|
|
||||||
* S - screen content (binary encoding of the entire screen with simple compression)
|
|
||||||
* T - text labels - Title and buttons, \0x01-separated
|
|
||||||
* B - beep
|
|
||||||
* . - heartbeat
|
|
||||||
*
|
|
||||||
* --- Tx messages ---
|
|
||||||
* s - string
|
|
||||||
* b - action button
|
|
||||||
* p - mb press
|
|
||||||
* r - mb release
|
|
||||||
* m - mouse move
|
|
||||||
*/
|
|
||||||
var Input = (function() {
|
|
||||||
var opts = {
|
|
||||||
np_alt: false,
|
|
||||||
cu_alt: false,
|
|
||||||
fn_alt: false,
|
|
||||||
mt_click: false,
|
|
||||||
mt_move: false,
|
|
||||||
no_keys: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Send a literal message */
|
|
||||||
function sendStrMsg(str) {
|
|
||||||
return Conn.send("s"+str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Send a button event */
|
|
||||||
function sendBtnMsg(n) {
|
|
||||||
Conn.send("b"+Chr(n));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Fn alt choice for key message */
|
|
||||||
function fa(alt, normal) {
|
|
||||||
return opts.fn_alt ? alt : normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Cursor alt choice for key message */
|
|
||||||
function ca(alt, normal) {
|
|
||||||
return opts.cu_alt ? alt : normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Numpad alt choice for key message */
|
|
||||||
function na(alt, normal) {
|
|
||||||
return opts.np_alt ? alt : normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _bindFnKeys() {
|
|
||||||
var keymap = {
|
|
||||||
'tab': '\x09',
|
|
||||||
'backspace': '\x08',
|
|
||||||
'enter': '\x0d',
|
|
||||||
'ctrl+enter': '\x0a',
|
|
||||||
'esc': '\x1b',
|
|
||||||
'up': ca('\x1bOA', '\x1b[A'),
|
|
||||||
'down': ca('\x1bOB', '\x1b[B'),
|
|
||||||
'right': ca('\x1bOC', '\x1b[C'),
|
|
||||||
'left': ca('\x1bOD', '\x1b[D'),
|
|
||||||
'home': ca('\x1bOH', fa('\x1b[H', '\x1b[1~')),
|
|
||||||
'insert': '\x1b[2~',
|
|
||||||
'delete': '\x1b[3~',
|
|
||||||
'end': ca('\x1bOF', fa('\x1b[F', '\x1b[4~')),
|
|
||||||
'pageup': '\x1b[5~',
|
|
||||||
'pagedown': '\x1b[6~',
|
|
||||||
'f1': fa('\x1bOP', '\x1b[11~'),
|
|
||||||
'f2': fa('\x1bOQ', '\x1b[12~'),
|
|
||||||
'f3': fa('\x1bOR', '\x1b[13~'),
|
|
||||||
'f4': fa('\x1bOS', '\x1b[14~'),
|
|
||||||
'f5': '\x1b[15~', // note the disconnect
|
|
||||||
'f6': '\x1b[17~',
|
|
||||||
'f7': '\x1b[18~',
|
|
||||||
'f8': '\x1b[19~',
|
|
||||||
'f9': '\x1b[20~',
|
|
||||||
'f10': '\x1b[21~', // note the disconnect
|
|
||||||
'f11': '\x1b[23~',
|
|
||||||
'f12': '\x1b[24~',
|
|
||||||
'shift+f1': fa('\x1bO1;2P', '\x1b[25~'),
|
|
||||||
'shift+f2': fa('\x1bO1;2Q', '\x1b[26~'), // note the disconnect
|
|
||||||
'shift+f3': fa('\x1bO1;2R', '\x1b[28~'),
|
|
||||||
'shift+f4': fa('\x1bO1;2S', '\x1b[29~'), // note the disconnect
|
|
||||||
'shift+f5': fa('\x1b[15;2~', '\x1b[31~'),
|
|
||||||
'shift+f6': fa('\x1b[17;2~', '\x1b[32~'),
|
|
||||||
'shift+f7': fa('\x1b[18;2~', '\x1b[33~'),
|
|
||||||
'shift+f8': fa('\x1b[19;2~', '\x1b[34~'),
|
|
||||||
'shift+f9': fa('\x1b[20;2~', '\x1b[35~'), // 35-38 are not standard - but what is?
|
|
||||||
'shift+f10': fa('\x1b[21;2~', '\x1b[36~'),
|
|
||||||
'shift+f11': fa('\x1b[22;2~', '\x1b[37~'),
|
|
||||||
'shift+f12': fa('\x1b[23;2~', '\x1b[38~'),
|
|
||||||
'np_0': na('\x1bOp', '0'),
|
|
||||||
'np_1': na('\x1bOq', '1'),
|
|
||||||
'np_2': na('\x1bOr', '2'),
|
|
||||||
'np_3': na('\x1bOs', '3'),
|
|
||||||
'np_4': na('\x1bOt', '4'),
|
|
||||||
'np_5': na('\x1bOu', '5'),
|
|
||||||
'np_6': na('\x1bOv', '6'),
|
|
||||||
'np_7': na('\x1bOw', '7'),
|
|
||||||
'np_8': na('\x1bOx', '8'),
|
|
||||||
'np_9': na('\x1bOy', '9'),
|
|
||||||
'np_mul': na('\x1bOR', '*'),
|
|
||||||
'np_add': na('\x1bOl', '+'),
|
|
||||||
'np_sub': na('\x1bOS', '-'),
|
|
||||||
'np_point': na('\x1bOn', '.'),
|
|
||||||
'np_div': na('\x1bOQ', '/'),
|
|
||||||
// we don't implement numlock key (should change in numpad_alt mode, but it's even more useless than the rest)
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var k in keymap) {
|
|
||||||
if (keymap.hasOwnProperty(k)) {
|
|
||||||
bind(k, keymap[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Bind a keystroke to message */
|
|
||||||
function bind(combo, str) {
|
|
||||||
// mac fix - allow also cmd
|
|
||||||
if (combo.indexOf('ctrl+') !== -1) {
|
|
||||||
combo += ',' + combo.replace('ctrl', 'command');
|
|
||||||
}
|
|
||||||
|
|
||||||
// unbind possible old binding
|
|
||||||
key.unbind(combo);
|
|
||||||
|
|
||||||
key(combo, function (e) {
|
|
||||||
if (opts.no_keys) return;
|
|
||||||
e.preventDefault();
|
|
||||||
sendStrMsg(str)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Bind/rebind key messages */
|
|
||||||
function _initKeys() {
|
|
||||||
// This takes care of text characters typed
|
|
||||||
window.addEventListener('keypress', function(evt) {
|
|
||||||
if (opts.no_keys) return;
|
|
||||||
var str = '';
|
|
||||||
if (evt.key) str = evt.key;
|
|
||||||
else if (evt.which) str = String.fromCodePoint(evt.which);
|
|
||||||
if (str.length>0 && str.charCodeAt(0) >= 32) {
|
|
||||||
// console.log("Typed ", str);
|
|
||||||
sendStrMsg(str);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// ctrl-letter codes are sent as simple low ASCII codes
|
|
||||||
for (var i = 1; i<=26;i++) {
|
|
||||||
bind('ctrl+' + String.fromCharCode(96+i), String.fromCharCode(i));
|
|
||||||
}
|
|
||||||
bind('ctrl+]', '\x1b'); // alternate way to enter ESC
|
|
||||||
bind('ctrl+\\', '\x1c');
|
|
||||||
bind('ctrl+[', '\x1d');
|
|
||||||
bind('ctrl+^', '\x1e');
|
|
||||||
bind('ctrl+_', '\x1f');
|
|
||||||
|
|
||||||
_bindFnKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
// mouse button states
|
|
||||||
var mb1 = 0;
|
|
||||||
var mb2 = 0;
|
|
||||||
var mb3 = 0;
|
|
||||||
|
|
||||||
/** Init the Input module */
|
|
||||||
function init() {
|
|
||||||
_initKeys();
|
|
||||||
|
|
||||||
// Button presses
|
|
||||||
$('#action-buttons button').forEach(function(s) {
|
|
||||||
s.addEventListener('click', function() {
|
|
||||||
sendBtnMsg(+this.dataset['n']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// global mouse state tracking - for motion reporting
|
|
||||||
window.addEventListener('mousedown', function(evt) {
|
|
||||||
if (evt.button == 0) mb1 = 1;
|
|
||||||
if (evt.button == 1) mb2 = 1;
|
|
||||||
if (evt.button == 2) mb3 = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('mouseup', function(evt) {
|
|
||||||
if (evt.button == 0) mb1 = 0;
|
|
||||||
if (evt.button == 1) mb2 = 0;
|
|
||||||
if (evt.button == 2) mb3 = 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Prepare modifiers byte for mouse message */
|
|
||||||
function packModifiersForMouse() {
|
|
||||||
return (key.isModifier('ctrl')?1:0) |
|
|
||||||
(key.isModifier('shift')?2:0) |
|
|
||||||
(key.isModifier('alt')?4:0) |
|
|
||||||
(key.isModifier('meta')?8:0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
/** Init the Input module */
|
|
||||||
init: init,
|
|
||||||
|
|
||||||
/** Send a literal string message */
|
|
||||||
sendString: sendStrMsg,
|
|
||||||
|
|
||||||
/** Enable alternate key modes (cursors, numpad, fn) */
|
|
||||||
setAlts: function(cu, np, fn) {
|
|
||||||
if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) {
|
|
||||||
opts.cu_alt = cu;
|
|
||||||
opts.np_alt = np;
|
|
||||||
opts.fn_alt = fn;
|
|
||||||
|
|
||||||
// rebind keys - codes have changed
|
|
||||||
_bindFnKeys();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setMouseMode: function(click, move) {
|
|
||||||
opts.mt_click = click;
|
|
||||||
opts.mt_move = move;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Mouse events
|
|
||||||
onMouseMove: function (x, y) {
|
|
||||||
if (!opts.mt_move) return;
|
|
||||||
var b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0;
|
|
||||||
var m = packModifiersForMouse();
|
|
||||||
Conn.send("m" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
|
||||||
},
|
|
||||||
onMouseDown: function (x, y, b) {
|
|
||||||
if (!opts.mt_click) return;
|
|
||||||
if (b > 3 || b < 1) return;
|
|
||||||
var m = packModifiersForMouse();
|
|
||||||
Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
|
||||||
// console.log("B ",b," M ",m);
|
|
||||||
},
|
|
||||||
onMouseUp: function (x, y, b) {
|
|
||||||
if (!opts.mt_click) return;
|
|
||||||
if (b > 3 || b < 1) return;
|
|
||||||
var m = packModifiersForMouse();
|
|
||||||
Conn.send("r" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
|
||||||
// console.log("B ",b," M ",m);
|
|
||||||
},
|
|
||||||
onMouseWheel: function (x, y, dir) {
|
|
||||||
if (!opts.mt_click) return;
|
|
||||||
// -1 ... btn 4 (away from user)
|
|
||||||
// +1 ... btn 5 (towards user)
|
|
||||||
var m = packModifiersForMouse();
|
|
||||||
var b = (dir < 0 ? 4 : 5);
|
|
||||||
Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
|
||||||
// console.log("B ",b," M ",m);
|
|
||||||
},
|
|
||||||
mouseTracksClicks: function() {
|
|
||||||
return opts.mt_click;
|
|
||||||
},
|
|
||||||
blockKeys: function(yes) {
|
|
||||||
opts.no_keys = yes;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
@@ -1,378 +0,0 @@
|
|||||||
var Screen = (function () {
|
|
||||||
var W = 0, H = 0; // dimensions
|
|
||||||
var inited = false;
|
|
||||||
|
|
||||||
var cursor = {
|
|
||||||
a: false, // active (blink state)
|
|
||||||
x: 0, // 0-based coordinates
|
|
||||||
y: 0,
|
|
||||||
fg: 7, // colors 0-15
|
|
||||||
bg: 0,
|
|
||||||
attrs: 0,
|
|
||||||
suppress: false, // do not turn on in blink interval (for safe moving)
|
|
||||||
forceOn: false, // force on unless hanging: used to keep cursor visible during move
|
|
||||||
hidden: false, // do not show (DEC opt)
|
|
||||||
hanging: false, // cursor at column "W+1" - not visible
|
|
||||||
};
|
|
||||||
|
|
||||||
var screen = [];
|
|
||||||
var blinkIval;
|
|
||||||
var cursorFlashStartIval;
|
|
||||||
|
|
||||||
// Some non-bold Fraktur symbols are outside the contiguous block
|
|
||||||
var frakturExceptions = {
|
|
||||||
'C': '\u212d',
|
|
||||||
'H': '\u210c',
|
|
||||||
'I': '\u2111',
|
|
||||||
'R': '\u211c',
|
|
||||||
'Z': '\u2128',
|
|
||||||
};
|
|
||||||
|
|
||||||
// for BEL
|
|
||||||
var audioCtx = null;
|
|
||||||
try {
|
|
||||||
audioCtx = new (window.AudioContext || window.audioContext || window.webkitAudioContext)();
|
|
||||||
} catch (er) {
|
|
||||||
console.error("No AudioContext!", er);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get cell under cursor */
|
|
||||||
function _curCell() {
|
|
||||||
return screen[cursor.y*W + cursor.x];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Safely move cursor */
|
|
||||||
function cursorSet(y, x) {
|
|
||||||
// Hide and prevent from showing up during the move
|
|
||||||
cursor.suppress = true;
|
|
||||||
_draw(_curCell(), false);
|
|
||||||
cursor.x = x;
|
|
||||||
cursor.y = y;
|
|
||||||
// Show again
|
|
||||||
cursor.suppress = false;
|
|
||||||
_draw(_curCell());
|
|
||||||
}
|
|
||||||
|
|
||||||
function alpha2fraktur(t) {
|
|
||||||
// perform substitution
|
|
||||||
if (t >= 'a' && t <= 'z') {
|
|
||||||
t = String.fromCodePoint(0x1d51e - 97 + t.charCodeAt(0));
|
|
||||||
}
|
|
||||||
else if (t >= 'A' && t <= 'Z') {
|
|
||||||
// this set is incomplete, some exceptions are needed
|
|
||||||
if (frakturExceptions.hasOwnProperty(t)) {
|
|
||||||
t = frakturExceptions[t];
|
|
||||||
} else {
|
|
||||||
t = String.fromCodePoint(0x1d504 - 65 + t.charCodeAt(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update cell on display. inv = invert (for cursor) */
|
|
||||||
function _draw(cell, inv) {
|
|
||||||
if (!cell) return;
|
|
||||||
if (typeof inv == 'undefined') {
|
|
||||||
inv = cursor.a && cursor.x == cell.x && cursor.y == cell.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fg, bg, cn, t;
|
|
||||||
|
|
||||||
fg = inv ? cell.bg : cell.fg;
|
|
||||||
bg = inv ? cell.fg : cell.bg;
|
|
||||||
|
|
||||||
t = cell.t;
|
|
||||||
if (!t.length) t = ' ';
|
|
||||||
|
|
||||||
cn = 'fg' + fg + ' bg' + bg;
|
|
||||||
if (cell.attrs & (1<<0)) cn += ' bold';
|
|
||||||
if (cell.attrs & (1<<1)) cn += ' faint';
|
|
||||||
if (cell.attrs & (1<<2)) cn += ' italic';
|
|
||||||
if (cell.attrs & (1<<3)) cn += ' under';
|
|
||||||
if (cell.attrs & (1<<4)) cn += ' blink';
|
|
||||||
if (cell.attrs & (1<<5)) {
|
|
||||||
cn += ' fraktur';
|
|
||||||
t = alpha2fraktur(t);
|
|
||||||
}
|
|
||||||
if (cell.attrs & (1<<6)) cn += ' strike';
|
|
||||||
|
|
||||||
cell.slot.textContent = t;
|
|
||||||
cell.elem.className = cn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Show entire screen */
|
|
||||||
function _drawAll() {
|
|
||||||
for (var i = W*H-1; i>=0; i--) {
|
|
||||||
_draw(screen[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _rebuild(rows, cols) {
|
|
||||||
W = cols;
|
|
||||||
H = rows;
|
|
||||||
|
|
||||||
/* Build screen & show */
|
|
||||||
var cOuter, cInner, cell, screenDiv = qs('#screen');
|
|
||||||
|
|
||||||
// Empty the screen node
|
|
||||||
while (screenDiv.firstChild) screenDiv.removeChild(screenDiv.firstChild);
|
|
||||||
|
|
||||||
screen = [];
|
|
||||||
|
|
||||||
for(var i = 0; i < W*H; i++) {
|
|
||||||
cOuter = mk('span');
|
|
||||||
cInner = mk('span');
|
|
||||||
|
|
||||||
/* Mouse tracking */
|
|
||||||
(function() {
|
|
||||||
var x = i % W;
|
|
||||||
var y = Math.floor(i / W);
|
|
||||||
cOuter.addEventListener('mouseenter', function (evt) {
|
|
||||||
Input.onMouseMove(x, y);
|
|
||||||
});
|
|
||||||
cOuter.addEventListener('mousedown', function (evt) {
|
|
||||||
Input.onMouseDown(x, y, evt.button+1);
|
|
||||||
});
|
|
||||||
cOuter.addEventListener('mouseup', function (evt) {
|
|
||||||
Input.onMouseUp(x, y, evt.button+1);
|
|
||||||
});
|
|
||||||
cOuter.addEventListener('contextmenu', function (evt) {
|
|
||||||
if (Input.mouseTracksClicks()) {
|
|
||||||
evt.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
cOuter.addEventListener('mousewheel', function (evt) {
|
|
||||||
Input.onMouseWheel(x, y, evt.deltaY>0?1:-1);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
|
|
||||||
/* End of line */
|
|
||||||
if ((i > 0) && (i % W == 0)) {
|
|
||||||
screenDiv.appendChild(mk('br'));
|
|
||||||
}
|
|
||||||
/* The cell */
|
|
||||||
cOuter.appendChild(cInner);
|
|
||||||
screenDiv.appendChild(cOuter);
|
|
||||||
|
|
||||||
cell = {
|
|
||||||
t: ' ',
|
|
||||||
fg: 7,
|
|
||||||
bg: 0, // the colors will be replaced immediately as we receive data (user won't see this)
|
|
||||||
attrs: 0,
|
|
||||||
elem: cOuter,
|
|
||||||
slot: cInner,
|
|
||||||
x: i % W,
|
|
||||||
y: Math.floor(i / W),
|
|
||||||
};
|
|
||||||
screen.push(cell);
|
|
||||||
_draw(cell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Init the terminal */
|
|
||||||
function _init() {
|
|
||||||
/* Cursor blinking */
|
|
||||||
clearInterval(blinkIval);
|
|
||||||
blinkIval = setInterval(function () {
|
|
||||||
cursor.a = !cursor.a;
|
|
||||||
if (cursor.hidden || cursor.hanging) {
|
|
||||||
cursor.a = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cursor.suppress) {
|
|
||||||
_draw(_curCell(), cursor.forceOn || cursor.a);
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
/* blink attribute animation */
|
|
||||||
setInterval(function () {
|
|
||||||
$('#screen').removeClass('blink-hide');
|
|
||||||
setTimeout(function () {
|
|
||||||
$('#screen').addClass('blink-hide');
|
|
||||||
}, 800); // 200 ms ON
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
inited = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// constants for decoding the update blob
|
|
||||||
var SEQ_SET_COLOR_ATTR = 1;
|
|
||||||
var SEQ_REPEAT = 2;
|
|
||||||
var SEQ_SET_COLOR = 3;
|
|
||||||
var SEQ_SET_ATTR = 4;
|
|
||||||
|
|
||||||
/** Parse received screen update object (leading S removed already) */
|
|
||||||
function _load_content(str) {
|
|
||||||
var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, attrs, cell;
|
|
||||||
|
|
||||||
if (!inited) _init();
|
|
||||||
|
|
||||||
var cursorMoved;
|
|
||||||
|
|
||||||
// Set size
|
|
||||||
num = parse2B(str, i); i += 2; // height
|
|
||||||
num2 = parse2B(str, i); i += 2; // width
|
|
||||||
if (num != H || num2 != W) {
|
|
||||||
_rebuild(num, num2);
|
|
||||||
}
|
|
||||||
// console.log("Size ",num, num2);
|
|
||||||
|
|
||||||
// Cursor position
|
|
||||||
num = parse2B(str, i); i += 2; // row
|
|
||||||
num2 = parse2B(str, i); i += 2; // col
|
|
||||||
cursorMoved = (cursor.x != num2 || cursor.y != num);
|
|
||||||
cursorSet(num, num2);
|
|
||||||
// console.log("Cursor at ",num, num2);
|
|
||||||
|
|
||||||
// Attributes
|
|
||||||
num = parse2B(str, i); i += 2; // fg bg attribs
|
|
||||||
cursor.hidden = !(num & (1<<0)); // DEC opt "visible"
|
|
||||||
cursor.hanging = !!(num & (1<<1));
|
|
||||||
// console.log("Attributes word ",num.toString(16)+'h');
|
|
||||||
|
|
||||||
Input.setAlts(
|
|
||||||
!!(num & (1<<2)), // cursors alt
|
|
||||||
!!(num & (1<<3)), // numpad alt
|
|
||||||
!!(num & (1<<4)) // fn keys alt
|
|
||||||
);
|
|
||||||
|
|
||||||
var mt_click = !!(num & (1<<5));
|
|
||||||
var mt_move = !!(num & (1<<6));
|
|
||||||
Input.setMouseMode(
|
|
||||||
mt_click,
|
|
||||||
mt_move
|
|
||||||
);
|
|
||||||
$('#screen').toggleClass('noselect', mt_move);
|
|
||||||
|
|
||||||
var show_buttons = !!(num & (1<<7));
|
|
||||||
var show_config_links = !!(num & (1<<8));
|
|
||||||
$('.x-term-conf-btn').toggleClass('hidden', !show_config_links);
|
|
||||||
$('#action-buttons').toggleClass('hidden', !show_buttons);
|
|
||||||
|
|
||||||
fg = 7;
|
|
||||||
bg = 0;
|
|
||||||
attrs = 0;
|
|
||||||
|
|
||||||
// Here come the content
|
|
||||||
while(i < str.length && ci<W*H) {
|
|
||||||
|
|
||||||
j = str[i++];
|
|
||||||
jc = j.charCodeAt(0);
|
|
||||||
if (jc == SEQ_SET_COLOR_ATTR) {
|
|
||||||
num = parse3B(str, i); i += 3;
|
|
||||||
fg = num & 0x0F;
|
|
||||||
bg = (num & 0xF0) >> 4;
|
|
||||||
attrs = (num & 0xFF00)>>8;
|
|
||||||
}
|
|
||||||
else if (jc == SEQ_SET_COLOR) {
|
|
||||||
num = parse2B(str, i); i += 2;
|
|
||||||
fg = num & 0x0F;
|
|
||||||
bg = (num & 0xF0) >> 4;
|
|
||||||
}
|
|
||||||
else if (jc == SEQ_SET_ATTR) {
|
|
||||||
num = parse2B(str, i); i += 2;
|
|
||||||
attrs = num & 0xFF;
|
|
||||||
}
|
|
||||||
else if (jc == SEQ_REPEAT) {
|
|
||||||
num = parse2B(str, i); i += 2;
|
|
||||||
// console.log("Repeat x ",num);
|
|
||||||
for (; num>0 && ci<W*H; num--) {
|
|
||||||
cell = screen[ci++];
|
|
||||||
cell.fg = fg;
|
|
||||||
cell.bg = bg;
|
|
||||||
cell.t = t;
|
|
||||||
cell.attrs = attrs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cell = screen[ci++];
|
|
||||||
// Unique cell character
|
|
||||||
t = cell.t = j;
|
|
||||||
cell.fg = fg;
|
|
||||||
cell.bg = bg;
|
|
||||||
cell.attrs = attrs;
|
|
||||||
// console.log("Symbol ", j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_drawAll();
|
|
||||||
|
|
||||||
// if (!cursor.hidden || cursor.hanging || !cursor.suppress) {
|
|
||||||
// // hide cursor asap
|
|
||||||
// _draw(_curCell(), false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (cursorMoved) {
|
|
||||||
cursor.forceOn = true;
|
|
||||||
cursorFlashStartIval = setTimeout(function() {
|
|
||||||
cursor.forceOn = false;
|
|
||||||
}, 1200);
|
|
||||||
_draw(_curCell(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Apply labels to buttons and screen title (leading T removed already) */
|
|
||||||
function _load_labels(str) {
|
|
||||||
var pieces = str.split('\x01');
|
|
||||||
qs('h1').textContent = pieces[0];
|
|
||||||
$('#action-buttons button').forEach(function(x, i) {
|
|
||||||
var s = pieces[i+1].trim();
|
|
||||||
// if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically
|
|
||||||
x.innerHTML = s.length > 0 ? e(s) : " ";
|
|
||||||
x.style.opacity = s.length > 0 ? 1 : 0.2;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Audible beep for ASCII 7 */
|
|
||||||
function _beep() {
|
|
||||||
var osc, gain;
|
|
||||||
if (!audioCtx) return;
|
|
||||||
|
|
||||||
// Main beep
|
|
||||||
osc = audioCtx.createOscillator();
|
|
||||||
gain = audioCtx.createGain();
|
|
||||||
osc.connect(gain);
|
|
||||||
gain.connect(audioCtx.destination);
|
|
||||||
gain.gain.value = 0.5;
|
|
||||||
osc.frequency.value = 750;
|
|
||||||
osc.type = 'sine';
|
|
||||||
osc.start();
|
|
||||||
osc.stop(audioCtx.currentTime+0.05);
|
|
||||||
|
|
||||||
// Surrogate beep (making it sound like 'oops')
|
|
||||||
osc = audioCtx.createOscillator();
|
|
||||||
gain = audioCtx.createGain();
|
|
||||||
osc.connect(gain);
|
|
||||||
gain.connect(audioCtx.destination);
|
|
||||||
gain.gain.value = 0.2;
|
|
||||||
osc.frequency.value = 400;
|
|
||||||
osc.type = 'sine';
|
|
||||||
osc.start(audioCtx.currentTime+0.05);
|
|
||||||
osc.stop(audioCtx.currentTime+0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Load screen content from a binary sequence (new) */
|
|
||||||
function load(str) {
|
|
||||||
//console.log(JSON.stringify(str));
|
|
||||||
var content = str.substr(1);
|
|
||||||
switch(str.charAt(0)) {
|
|
||||||
case 'S':
|
|
||||||
_load_content(content);
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
_load_labels(content);
|
|
||||||
break;
|
|
||||||
case 'B':
|
|
||||||
_beep();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.warn("Bad data message type, ignoring.");
|
|
||||||
console.log(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
load: load, // full load (string)
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
/** File upload utility */
|
|
||||||
var TermUpl = (function() {
|
|
||||||
var lines, // array of lines without newlines
|
|
||||||
line_i, // current line index
|
|
||||||
fuTout, // timeout handle for line sending
|
|
||||||
send_delay_ms, // delay between lines (ms)
|
|
||||||
nl_str, // newline string to use
|
|
||||||
curLine, // current line (when using fuOil)
|
|
||||||
inline_pos; // Offset in line (for long lines)
|
|
||||||
|
|
||||||
// lines longer than this are split to chunks
|
|
||||||
// sending a super-ling string through the socket is not a good idea
|
|
||||||
var MAX_LINE_LEN = 128;
|
|
||||||
|
|
||||||
function fuOpen() {
|
|
||||||
fuStatus("Ready...");
|
|
||||||
Modal.show('#fu_modal', onClose);
|
|
||||||
$('#fu_form').toggleClass('busy', false);
|
|
||||||
Input.blockKeys(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onClose() {
|
|
||||||
console.log("Upload modal closed.");
|
|
||||||
clearTimeout(fuTout);
|
|
||||||
line_i = 0;
|
|
||||||
Input.blockKeys(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fuStatus(msg) {
|
|
||||||
qs('#fu_prog').textContent = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fuSend() {
|
|
||||||
var v = qs('#fu_text').value;
|
|
||||||
if (!v.length) {
|
|
||||||
fuClose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lines = v.split('\n');
|
|
||||||
line_i = 0;
|
|
||||||
inline_pos = 0; // offset in line
|
|
||||||
send_delay_ms = qs('#fu_delay').value;
|
|
||||||
|
|
||||||
// sanitize - 0 causes overflows
|
|
||||||
if (send_delay_ms < 0) {
|
|
||||||
send_delay_ms = 0;
|
|
||||||
qs('#fu_delay').value = send_delay_ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
nl_str = {
|
|
||||||
'CR': '\r',
|
|
||||||
'LF': '\n',
|
|
||||||
'CRLF': '\r\n',
|
|
||||||
}[qs('#fu_crlf').value];
|
|
||||||
|
|
||||||
$('#fu_form').toggleClass('busy', true);
|
|
||||||
fuStatus("Starting...");
|
|
||||||
fuSendLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
function fuSendLine() {
|
|
||||||
if (!$('#fu_modal').hasClass('visible')) {
|
|
||||||
// Modal is closed, cancel
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Conn.canSend()) {
|
|
||||||
// postpone
|
|
||||||
fuTout = setTimeout(fuSendLine, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inline_pos == 0) {
|
|
||||||
curLine = lines[line_i++] + nl_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
var chunk;
|
|
||||||
if ((curLine.length - inline_pos) <= MAX_LINE_LEN) {
|
|
||||||
chunk = curLine.substr(inline_pos, MAX_LINE_LEN);
|
|
||||||
inline_pos = 0;
|
|
||||||
} else {
|
|
||||||
chunk = curLine.substr(inline_pos, MAX_LINE_LEN);
|
|
||||||
inline_pos += MAX_LINE_LEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Input.sendString(chunk)) {
|
|
||||||
fuStatus("FAILED!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var all = lines.length;
|
|
||||||
|
|
||||||
fuStatus(line_i+" / "+all+ " ("+(Math.round((line_i/all)*1000)/10)+"%)");
|
|
||||||
|
|
||||||
if (lines.length > line_i || inline_pos > 0) {
|
|
||||||
fuTout = setTimeout(fuSendLine, send_delay_ms);
|
|
||||||
} else {
|
|
||||||
closeWhenReady();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeWhenReady() {
|
|
||||||
if (!Conn.canSend()) {
|
|
||||||
// stuck in XOFF still, wait to process...
|
|
||||||
fuStatus("Waiting for Tx buffer...");
|
|
||||||
setTimeout(closeWhenReady, 100);
|
|
||||||
} else {
|
|
||||||
fuStatus("Done.");
|
|
||||||
// delay to show it
|
|
||||||
setTimeout(function() {
|
|
||||||
fuClose();
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fuClose() {
|
|
||||||
Modal.hide('#fu_modal');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
init: function() {
|
|
||||||
qs('#fu_file').addEventListener('change', function (evt) {
|
|
||||||
var reader = new FileReader();
|
|
||||||
var file = evt.target.files[0];
|
|
||||||
console.log("Selected file type: "+file.type);
|
|
||||||
if (!file.type.match(/text\/.*|application\/(json|csv|.*xml.*|.*script.*)/)) {
|
|
||||||
// Deny load of blobs like img - can crash browser and will get corrupted anyway
|
|
||||||
if (!confirm("This does not look like a text file: "+file.type+"\nReally load?")) {
|
|
||||||
qs('#fu_file').value = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.onload = function(e) {
|
|
||||||
var txt = e.target.result.replace(/[\r\n]+/,'\n');
|
|
||||||
qs('#fu_text').value = txt;
|
|
||||||
};
|
|
||||||
console.log("Loading file...");
|
|
||||||
reader.readAsText(file);
|
|
||||||
}, false);
|
|
||||||
},
|
|
||||||
close: fuClose,
|
|
||||||
start: fuSend,
|
|
||||||
open: fuOpen,
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
/** Make a node */
|
|
||||||
function mk(e) {return document.createElement(e)}
|
|
||||||
|
|
||||||
/** Find one by query */
|
|
||||||
function qs(s) {return document.querySelector(s)}
|
|
||||||
|
|
||||||
/** Find all by query */
|
|
||||||
function qsa(s) {return document.querySelectorAll(s)}
|
|
||||||
|
|
||||||
/** Convert any to bool safely */
|
|
||||||
function bool(x) {
|
|
||||||
return (x === 1 || x === '1' || x === true || x === 'true');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter 'spacebar' and 'return' from keypress handler,
|
|
||||||
* and when they're pressed, fire the callback.
|
|
||||||
* use $(...).on('keypress', cr(handler))
|
|
||||||
*/
|
|
||||||
function cr(hdl) {
|
|
||||||
return function(e) {
|
|
||||||
if (e.which == 10 || e.which == 13 || e.which == 32) {
|
|
||||||
hdl();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Extend an objects with options */
|
|
||||||
function extend(defaults, options) {
|
|
||||||
var target = {};
|
|
||||||
|
|
||||||
Object.keys(defaults).forEach(function(k){
|
|
||||||
target[k] = defaults[k];
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(options).forEach(function(k){
|
|
||||||
target[k] = options[k];
|
|
||||||
});
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Escape string for use as literal in RegExp */
|
|
||||||
function rgxe(str) {
|
|
||||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Format number to N decimal places, output as string */
|
|
||||||
function numfmt(x, places) {
|
|
||||||
var pow = Math.pow(10, places);
|
|
||||||
return Math.round(x*pow) / pow;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get millisecond timestamp */
|
|
||||||
function msNow() {
|
|
||||||
return +(new Date);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get ms elapsed since msNow() */
|
|
||||||
function msElapsed(start) {
|
|
||||||
return msNow() - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Shim for log base 10 */
|
|
||||||
Math.log10 = Math.log10 || function(x) {
|
|
||||||
return Math.log(x) / Math.LN10;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a substitution in the given string.
|
|
||||||
*
|
|
||||||
* Arguments - array or list of replacements.
|
|
||||||
* Arguments numeric keys will replace {0}, {1} etc.
|
|
||||||
* Named keys also work, ie. {foo: "bar"} -> replaces {foo} with bar.
|
|
||||||
*
|
|
||||||
* Braces are added to keys if missing.
|
|
||||||
*
|
|
||||||
* @returns {String} result
|
|
||||||
*/
|
|
||||||
String.prototype.format = function () {
|
|
||||||
var out = this;
|
|
||||||
var repl = arguments;
|
|
||||||
|
|
||||||
if (arguments.length == 1 && (Array.isArray(arguments[0]) || typeof arguments[0] == 'object')) {
|
|
||||||
repl = arguments[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var ph in repl) {
|
|
||||||
if (repl.hasOwnProperty(ph)) {
|
|
||||||
var ph_orig = ph;
|
|
||||||
|
|
||||||
if (!ph.match(/^\{.*\}$/)) {
|
|
||||||
ph = '{' + ph + '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace all occurrences
|
|
||||||
var pattern = new RegExp(rgxe(ph), "g");
|
|
||||||
out = out.replace(pattern, repl[ph_orig]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** HTML escape */
|
|
||||||
function e(str) {
|
|
||||||
return $.htmlEscape(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check for undefined */
|
|
||||||
function undef(x) {
|
|
||||||
return typeof x == 'undefined';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Safe json parse */
|
|
||||||
function jsp(str) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(str);
|
|
||||||
} catch(e) {
|
|
||||||
console.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a character from ASCII code */
|
|
||||||
function Chr(n) {
|
|
||||||
return String.fromCharCode(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Decode number from 2B encoding */
|
|
||||||
function parse2B(s, i) {
|
|
||||||
return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Decode number from 3B encoding */
|
|
||||||
function parse3B(s, i) {
|
|
||||||
return (s.charCodeAt(i) - 1) + (s.charCodeAt(i+1) - 1) * 127 + (s.charCodeAt(i+2) - 1) * 127 * 127;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Encode using 2B encoding, returns string. */
|
|
||||||
function encode2B(n) {
|
|
||||||
var lsb, msb;
|
|
||||||
lsb = (n % 127);
|
|
||||||
n = ((n - lsb) / 127);
|
|
||||||
lsb += 1;
|
|
||||||
msb = (n + 1);
|
|
||||||
return Chr(lsb) + Chr(msb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Encode using 3B encoding, returns string. */
|
|
||||||
function encode3B(n) {
|
|
||||||
var lsb, msb, xsb;
|
|
||||||
lsb = (n % 127);
|
|
||||||
n = (n - lsb) / 127;
|
|
||||||
lsb += 1;
|
|
||||||
msb = (n % 127);
|
|
||||||
n = (n - msb) / 127;
|
|
||||||
msb += 1;
|
|
||||||
xsb = (n + 1);
|
|
||||||
return Chr(lsb) + Chr(msb) + Chr(xsb);
|
|
||||||
}
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
(function(w) {
|
|
||||||
var authStr = ['Open', 'WEP', 'WPA', 'WPA2', 'WPA/WPA2'];
|
|
||||||
var curSSID;
|
|
||||||
|
|
||||||
// Get XX % for a slider input
|
|
||||||
function rangePt(inp) {
|
|
||||||
return Math.round(((inp.value / inp.max)*100)) + '%';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display selected STA SSID etc
|
|
||||||
function selectSta(name, password, ip) {
|
|
||||||
$('#sta_ssid').val(name);
|
|
||||||
$('#sta_password').val(password);
|
|
||||||
|
|
||||||
$('#sta-nw').toggleClass('hidden', name.length == 0);
|
|
||||||
$('#sta-nw-nil').toggleClass('hidden', name.length > 0);
|
|
||||||
|
|
||||||
$('#sta-nw .essid').html(e(name));
|
|
||||||
var nopw = undef(password) || password.length == 0;
|
|
||||||
$('#sta-nw .passwd').toggleClass('hidden', nopw);
|
|
||||||
$('#sta-nw .nopasswd').toggleClass('hidden', !nopw);
|
|
||||||
$('#sta-nw .ip').html(ip.length>0 ? tr('wifi.connected_ip_is')+ip : tr('wifi.not_conn'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update display for received response */
|
|
||||||
function onScan(resp, status) {
|
|
||||||
//var ap_json = {
|
|
||||||
// "result": {
|
|
||||||
// "inProgress": "0",
|
|
||||||
// "APs": [
|
|
||||||
// {"essid": "Chlivek", "bssid": "88:f7:c7:52:b3:99", "rssi": "204", "enc": "4", "channel": "1"},
|
|
||||||
// {"essid": "TyNikdy", "bssid": "5c:f4:ab:0d:f1:1b", "rssi": "164", "enc": "3", "channel": "1"},
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
//};
|
|
||||||
|
|
||||||
if (status != 200) {
|
|
||||||
// bad response
|
|
||||||
rescan(5000); // wait 5sm then retry
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
resp = JSON.parse(resp);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
rescan(5000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var done = !bool(resp.result.inProgress) && (resp.result.APs.length > 0);
|
|
||||||
rescan(done ? 15000 : 1000);
|
|
||||||
if (!done) return; // no redraw yet
|
|
||||||
|
|
||||||
// clear the AP list
|
|
||||||
var $list = $('#ap-list');
|
|
||||||
// remove old APs
|
|
||||||
$('#ap-list .AP').remove();
|
|
||||||
|
|
||||||
$list.toggleClass('hidden', !done);
|
|
||||||
$('#ap-loader').toggleClass('hidden', done);
|
|
||||||
|
|
||||||
// scan done
|
|
||||||
resp.result.APs.sort(function (a, b) {
|
|
||||||
return b.rssi - a.rssi;
|
|
||||||
}).forEach(function (ap) {
|
|
||||||
ap.enc = parseInt(ap.enc);
|
|
||||||
|
|
||||||
if (ap.enc > 4) return; // hide unsupported auths
|
|
||||||
|
|
||||||
var item = mk('div');
|
|
||||||
|
|
||||||
var $item = $(item)
|
|
||||||
.data('ssid', ap.essid)
|
|
||||||
.data('pwd', ap.enc)
|
|
||||||
.attr('tabindex', 0)
|
|
||||||
.addClass('AP');
|
|
||||||
|
|
||||||
// mark current SSID
|
|
||||||
if (ap.essid == curSSID) {
|
|
||||||
$item.addClass('selected');
|
|
||||||
}
|
|
||||||
|
|
||||||
var inner = mk('div');
|
|
||||||
$(inner).addClass('inner')
|
|
||||||
.htmlAppend('<div class="rssi">{0}</div>'.format(ap.rssi_perc))
|
|
||||||
.htmlAppend('<div class="essid" title="{0}">{0}</div>'.format($.htmlEscape(ap.essid)))
|
|
||||||
.htmlAppend('<div class="auth">{0}</div>'.format(authStr[ap.enc]));
|
|
||||||
|
|
||||||
$item.on('click', function () {
|
|
||||||
var $th = $(this);
|
|
||||||
|
|
||||||
var conn_ssid = $th.data('ssid');
|
|
||||||
var conn_pass = '';
|
|
||||||
|
|
||||||
if (+$th.data('pwd')) {
|
|
||||||
// this AP needs a password
|
|
||||||
conn_pass = prompt(tr("wifi.enter_passwd").replace(":ssid:", conn_ssid));
|
|
||||||
if (!conn_pass) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#sta_password').val(conn_pass);
|
|
||||||
$('#sta_ssid').val(conn_ssid);
|
|
||||||
selectSta(conn_ssid, conn_pass, '');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
item.appendChild(inner);
|
|
||||||
$list[0].appendChild(item);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function startScanning() {
|
|
||||||
$('#ap-loader').removeClass('hidden');
|
|
||||||
$('#ap-scan').addClass('hidden');
|
|
||||||
$('#ap-loader .anim-dots').html('.');
|
|
||||||
|
|
||||||
scanAPs();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Ask the CGI what APs are visible (async) */
|
|
||||||
function scanAPs() {
|
|
||||||
if (_demo) {
|
|
||||||
onScan(_demo_aps, 200);
|
|
||||||
} else {
|
|
||||||
$.get('http://' + _root + '/cfg/wifi/scan', onScan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function rescan(time) {
|
|
||||||
setTimeout(scanAPs, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set up the WiFi page */
|
|
||||||
function wifiInit(cfg) {
|
|
||||||
// Update slider value displays
|
|
||||||
$('.Row.range').forEach(function(x) {
|
|
||||||
var inp = x.querySelector('input');
|
|
||||||
var disp1 = x.querySelector('.x-disp1');
|
|
||||||
var disp2 = x.querySelector('.x-disp2');
|
|
||||||
var t = rangePt(inp);
|
|
||||||
$(disp1).html(t);
|
|
||||||
$(disp2).html(t);
|
|
||||||
$(inp).on('input', function() {
|
|
||||||
t = rangePt(inp);
|
|
||||||
$(disp1).html(t);
|
|
||||||
$(disp2).html(t);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Forget STA credentials
|
|
||||||
$('#forget-sta').on('click', function() {
|
|
||||||
selectSta('', '', '');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
selectSta(cfg.sta_ssid, cfg.sta_password, cfg.sta_active_ip);
|
|
||||||
curSSID = cfg.sta_active_ssid;
|
|
||||||
}
|
|
||||||
|
|
||||||
w.init = wifiInit;
|
|
||||||
w.startScanning = startScanning;
|
|
||||||
})(window.WiFi = {});
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
return [
|
|
||||||
'appname' => 'ESPTerm',
|
|
||||||
'appname_demo' => 'ESPTerm<sup> DEMO</sup>',
|
|
||||||
|
|
||||||
'menu.cfg_wifi' => 'WiFi Settings',
|
|
||||||
'menu.cfg_network' => 'Network Settings',
|
|
||||||
'menu.cfg_term' => 'Terminal Settings',
|
|
||||||
'menu.about' => 'About ESPTerm',
|
|
||||||
'menu.help' => 'Quick Reference',
|
|
||||||
'menu.term' => 'Back to Terminal',
|
|
||||||
'menu.cfg_system' => 'System Settings',
|
|
||||||
'menu.cfg_wifi_conn' => 'Connecting to Network',
|
|
||||||
|
|
||||||
'menu.settings' => 'Settings',
|
|
||||||
|
|
||||||
'title.term' => 'Terminal',
|
|
||||||
|
|
||||||
'term_nav.config' => 'Config',
|
|
||||||
'term_nav.wifi' => 'WiFi',
|
|
||||||
'term_nav.help' => 'Help',
|
|
||||||
'term_nav.about' => 'About',
|
|
||||||
'term_nav.paste' => 'Paste',
|
|
||||||
'term_nav.upload' => 'Upload',
|
|
||||||
'term_nav.keybd' => 'Keyboard',
|
|
||||||
'term_nav.paste_prompt' => 'Paste text to send:',
|
|
||||||
|
|
||||||
'net.ap' => 'DHCP Server (AP)',
|
|
||||||
'net.sta' => 'DHCP Client (Station)',
|
|
||||||
'net.sta_mac' => 'Station MAC',
|
|
||||||
'net.ap_mac' => 'AP MAC',
|
|
||||||
'net.details' => 'MAC addresses',
|
|
||||||
|
|
||||||
'term.defaults' => 'Initial Settings',
|
|
||||||
'term.expert' => 'Expert Options',
|
|
||||||
'term.explain_initials' => '
|
|
||||||
Those are the initial settings used after ESPTerm powers on or when the screen
|
|
||||||
reset command is received. Some options can be changed by the application via escape sequences,
|
|
||||||
those changes won\'t be saved in Flash.
|
|
||||||
',
|
|
||||||
'term.explain_expert' => '
|
|
||||||
Those are advanced config options that usually don\'t need to be changed.
|
|
||||||
Edit them only if you know what you\'re doing.',
|
|
||||||
|
|
||||||
'term.example' => 'Default colors preview',
|
|
||||||
|
|
||||||
'term.reset_screen' => 'Reset screen & parser',
|
|
||||||
'term.term_title' => 'Header text',
|
|
||||||
'term.term_width' => 'Width / height',
|
|
||||||
'term.default_fg_bg' => 'Text / background',
|
|
||||||
'term.buttons' => 'Button labels',
|
|
||||||
'term.theme' => 'Color scheme',
|
|
||||||
'term.parser_tout_ms' => 'Parser timeout',
|
|
||||||
'term.display_tout_ms' => 'Redraw delay',
|
|
||||||
'term.display_cooldown_ms' => 'Redraw cooldown',
|
|
||||||
'term.fn_alt_mode' => 'SS3 Fn keys',
|
|
||||||
'term.show_config_links' => 'Show nav links',
|
|
||||||
'term.show_buttons' => 'Show buttons',
|
|
||||||
'term.loopback' => 'Local Echo',
|
|
||||||
'term.button_msgs' => 'Button codes<br>(ASCII, dec, CSV)',
|
|
||||||
|
|
||||||
// terminal color labels
|
|
||||||
'color.0' => 'Black',
|
|
||||||
'color.1' => 'Red',
|
|
||||||
'color.2' => 'Green',
|
|
||||||
'color.3' => 'Yellow',
|
|
||||||
'color.4' => 'Blue',
|
|
||||||
'color.5' => 'Purple',
|
|
||||||
'color.6' => 'Cyan',
|
|
||||||
'color.7' => 'Silver',
|
|
||||||
'color.8' => 'Gray',
|
|
||||||
'color.9' => 'Light Red',
|
|
||||||
'color.10' => 'Light Green',
|
|
||||||
'color.11' => 'Light Yellow',
|
|
||||||
'color.12' => 'Light Blue',
|
|
||||||
'color.13' => 'Light Purple',
|
|
||||||
'color.14' => 'Light Cyan',
|
|
||||||
'color.15' => 'White',
|
|
||||||
|
|
||||||
'net.explain_sta' => '
|
|
||||||
Switch off Dynamic IP to configure the static IP address.',
|
|
||||||
|
|
||||||
'net.explain_ap' => '
|
|
||||||
Those settings affect the built-in DHCP server in AP mode.',
|
|
||||||
|
|
||||||
'net.ap_dhcp_time' => 'Lease time',
|
|
||||||
'net.ap_dhcp_start' => 'Pool start IP',
|
|
||||||
'net.ap_dhcp_end' => 'Pool end IP',
|
|
||||||
'net.ap_addr_ip' => 'Own IP address',
|
|
||||||
'net.ap_addr_mask' => 'Subnet mask',
|
|
||||||
|
|
||||||
'net.sta_dhcp_enable' => 'Use dynamic IP',
|
|
||||||
'net.sta_addr_ip' => 'ESPTerm static IP',
|
|
||||||
'net.sta_addr_mask' => 'Subnet mask',
|
|
||||||
'net.sta_addr_gw' => 'Gateway IP',
|
|
||||||
|
|
||||||
'wifi.ap' => 'Built-in Access Point',
|
|
||||||
'wifi.sta' => 'Join Existing Network',
|
|
||||||
|
|
||||||
'wifi.enable' => 'Enabled',
|
|
||||||
'wifi.tpw' => 'Transmit power',
|
|
||||||
'wifi.ap_channel' => 'Channel',
|
|
||||||
'wifi.ap_ssid' => 'AP SSID',
|
|
||||||
'wifi.ap_password' => 'Password',
|
|
||||||
'wifi.ap_hidden' => 'Hide SSID',
|
|
||||||
'wifi.sta_info' => 'Selected',
|
|
||||||
|
|
||||||
'wifi.not_conn' => 'Not connected.',
|
|
||||||
'wifi.sta_none' => 'None',
|
|
||||||
'wifi.sta_active_pw' => '🔒 Password saved',
|
|
||||||
'wifi.sta_active_nopw' => '🔓 Open access',
|
|
||||||
'wifi.connected_ip_is' => 'Connected, IP is ',
|
|
||||||
'wifi.sta_password' => 'Password:',
|
|
||||||
|
|
||||||
'wifi.scanning' => 'Scanning',
|
|
||||||
'wifi.scan_now' => 'Click here to start scanning!',
|
|
||||||
'wifi.cant_scan_no_sta' => 'Click here to enable client mode and start scanning!',
|
|
||||||
'wifi.select_ssid' => 'Available networks:',
|
|
||||||
'wifi.enter_passwd' => 'Enter password for ":ssid:"',
|
|
||||||
'wifi.sta_explain' => 'After selecting a network, press Apply to connect.',
|
|
||||||
|
|
||||||
'wifi.conn.status' => 'Status:',
|
|
||||||
'wifi.conn.back_to_config' => 'Back to WiFi config',
|
|
||||||
'wifi.conn.telemetry_lost' => 'Telemetry lost; something went wrong, or your device disconnected.',
|
|
||||||
'wifi.conn.explain_android_sucks' => '
|
|
||||||
If you\'re configuring ESPTerm via a smartphone, or were connected
|
|
||||||
from another external network, your device may lose connection and this
|
|
||||||
progress indicator won\'t work. Please wait a while (~ 15 seconds),
|
|
||||||
then check if the connection succeeded.',
|
|
||||||
|
|
||||||
'wifi.conn.explain_reset' => '
|
|
||||||
To force enable the built-in AP, hold the BOOT
|
|
||||||
button until the blue LED starts flashing. Hold the button longer (until the LED
|
|
||||||
flashes rapidly) for a "factory reset".',
|
|
||||||
|
|
||||||
'wifi.conn.disabled' =>"Station mode is disabled.",
|
|
||||||
'wifi.conn.idle' =>"Idle, not connected and has no IP.",
|
|
||||||
'wifi.conn.success' => "Connected! Received IP ",
|
|
||||||
'wifi.conn.working' => "Connecting to selected AP",
|
|
||||||
'wifi.conn.fail' => "Connection failed, check settings & try again. Cause: ",
|
|
||||||
|
|
||||||
'system.save_restore' => 'Save & Restore',
|
|
||||||
'system.confirm_restore' => 'Restore all settings to their default values?',
|
|
||||||
'system.confirm_restore_hard' =>
|
|
||||||
'Restore to firmware default settings? This will reset ' .
|
|
||||||
'all active settings and switch to AP mode with the default SSID.',
|
|
||||||
'system.confirm_store_defaults' =>
|
|
||||||
'Enter admin password to confirm you want to store the current settings as defaults.',
|
|
||||||
'system.password' => 'Admin password:',
|
|
||||||
'system.restore_defaults' => 'Reset active settings to defaults',
|
|
||||||
'system.write_defaults' => 'Save active settings as defaults',
|
|
||||||
'system.restore_hard' => 'Reset active settings to firmware defaults',
|
|
||||||
'system.explain_persist' => '
|
|
||||||
ESPTerm contains two persistent memory banks, one for default and
|
|
||||||
one for active settings. Active settings can be stored as defaults
|
|
||||||
by the administrator (password required).
|
|
||||||
',
|
|
||||||
'system.uart' => 'Serial Port',
|
|
||||||
'system.explain_uart' => '
|
|
||||||
This form controls the primary, communication UART. The debug UART is fixed at 115.200 baud, one stop-bit and no parity.
|
|
||||||
',
|
|
||||||
'uart.baud' => 'Baud rate',
|
|
||||||
'uart.parity' => 'Parity',
|
|
||||||
'uart.parity.none' => 'None',
|
|
||||||
'uart.parity.odd' => 'Odd',
|
|
||||||
'uart.parity.even' => 'Even',
|
|
||||||
'uart.stop_bits' => 'Stop-bits',
|
|
||||||
'uart.stop_bits.one' => 'One',
|
|
||||||
'uart.stop_bits.one_and_half' => 'One and half',
|
|
||||||
'uart.stop_bits.two' => 'Two',
|
|
||||||
|
|
||||||
'apply' => 'Apply!',
|
|
||||||
'enabled' => 'Enabled',
|
|
||||||
'disabled' => 'Disabled',
|
|
||||||
'yes' => 'Yes',
|
|
||||||
'no' => 'No',
|
|
||||||
'confirm' => 'OK',
|
|
||||||
'form_errors' => 'Validation errors for:',
|
|
||||||
];
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
echo "Packing js..."
|
|
||||||
|
|
||||||
cat jssrc/chibi.js \
|
|
||||||
jssrc/keymaster.js \
|
|
||||||
jssrc/utils.js \
|
|
||||||
jssrc/modal.js \
|
|
||||||
jssrc/notif.js \
|
|
||||||
jssrc/appcommon.js \
|
|
||||||
jssrc/lang.js \
|
|
||||||
jssrc/wifi.js \
|
|
||||||
jssrc/term_* \
|
|
||||||
jssrc/term.js > js/app.js
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<nav id="menu">
|
|
||||||
<div id="brand" tabindex=0><?= tr('appname'.(ESP_DEMO?'_demo':'')) ?></div>
|
|
||||||
<a href="<?= e(url('term')) ?>" class="icn-back"><?= tr('menu.term') ?></a>
|
|
||||||
<?php
|
|
||||||
// generate the menu
|
|
||||||
foreach ($_pages as $k => $page) {
|
|
||||||
if (strpos($page->bodyclass, 'cfg') === false) continue;
|
|
||||||
|
|
||||||
$sel = ($_GET['page'] == $k) ? 'selected' : '';
|
|
||||||
$text = $page->label;
|
|
||||||
$url = e(url($k));
|
|
||||||
echo "<a href=\"$url\" class=\"$page->icon $sel\">$text</a>";
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function menuOpen() { $('#menu').toggleClass('expanded') }
|
|
||||||
$('#brand').on('click', menuOpen).on('keypress', cr(menuOpen));
|
|
||||||
</script>
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<title><?= $_GET['PAGE_TITLE'] ?></title>
|
|
||||||
<link href="/css/app.css" rel="stylesheet">
|
|
||||||
<script src="/js/app.js"></script>
|
|
||||||
<script>
|
|
||||||
var _root = <?= JS_WEB_ROOT ?>;
|
|
||||||
var _demo = <?= (int)ESP_DEMO ?>;
|
|
||||||
<?php if($_GET['page']=='term'): ?>var _demo_screen = <?= ESP_DEMO ? DEMO_SCREEN : 0 ?>;<?php endif; ?>
|
|
||||||
<?php if($_GET['page']=='cfg_wifi'): ?>var _demo_aps = <?= ESP_DEMO ? json_encode(DEMO_APS) : '""' ?>;<?php endif; ?>
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body class="<?= $_GET['BODYCLASS'] ?>">
|
|
||||||
<div id="outer">
|
|
||||||
<?php
|
|
||||||
$cfg = false;
|
|
||||||
if (strpos($_GET['BODYCLASS'], 'cfg') !== false) {
|
|
||||||
$cfg = true;
|
|
||||||
require __DIR__ . '/_cfg_menu.php';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div id="content">
|
|
||||||
<img src="/img/loader.gif" alt="Loading…" id="loader">
|
|
||||||
<?php if ($cfg): ?>
|
|
||||||
<h1><?= tr('menu.' . $_GET['page']) ?></h1>
|
|
||||||
|
|
||||||
<div class="Box errors hidden">
|
|
||||||
<span class="lead"><?= tr('form_errors') ?></span> <span class="list"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php endif; ?>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
<?php if ($_GET['BODYCLASS'] !== 'page-term'): ?>
|
|
||||||
<div class="botpad"></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="NotifyMsg hidden" id="notif"></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
<div class="Box">
|
|
||||||
<img src="/img/cvut.svg" id="logo" class="mq-tablet-min">
|
|
||||||
<h2>ESP8266 Remote Terminal</h2>
|
|
||||||
|
|
||||||
<img src="/img/cvut.svg" id="logo2" class="mq-phone">
|
|
||||||
|
|
||||||
<p>
|
|
||||||
© Ondřej Hruška, 2016-2017
|
|
||||||
<<a href="mailto:ondra@ondrovo.com">ondra@ondrovo.com</a>>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="http://measure.feld.cvut.cz/" target="blank">Katedra měření, FEL ČVUT</a><br>
|
|
||||||
Department of Measurement, FEE CTU
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box">
|
|
||||||
<h2>Version</h2>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>ESPTerm</th>
|
|
||||||
<td>v%vers_fw%, built %date% at %time%</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>libesphttpd</th>
|
|
||||||
<td>v%vers_httpd%</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>ESP IoT SDK</th>
|
|
||||||
<td>v%vers_sdk%</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box">
|
|
||||||
<h2>Issues</h2>
|
|
||||||
<p>
|
|
||||||
Please report any issues to the <a href="%githubrepo%/issues">bugtracker</a> or send them by e-mail (see above).
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Firmware updates can be downloaded from the <a href="%githubrepo%/releases">releases page</a> and flashed
|
|
||||||
with <a href="https://github.com/espressif/esptool">esptool.py</a>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box">
|
|
||||||
<h2>Contributing</h2>
|
|
||||||
<p>
|
|
||||||
<i class="icn-github"></i> You're welcome to submit your improvements and ideas to our <a href="%githubrepo%">GitHub repository</a>!
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<i class="icn-donate"></i> If you'd like to donate, please try <a href="https://paypal.me/mightypork">PayPal</a> or
|
|
||||||
<a href="https://liberapay.com/MightyPork/">LiberaPay</a>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box">
|
|
||||||
<h2>Thanks</h2>
|
|
||||||
<p>
|
|
||||||
The webserver is based on a <a href="https://github.com/MightyPork/libesphttpd">fork</a> of the
|
|
||||||
<a href="https://github.com/Spritetm/esphttpd">esphttpd</a> library by Jeroen Domburg (Sprite_tm).
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Using (modified) JS library <a href="https://github.com/kylebarrow/chibi">chibi.js</a> by
|
|
||||||
Kyle Barrow as a lightweight jQuery alternative.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
<?php
|
|
||||||
$ipmask='pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}$"';
|
|
||||||
?>
|
|
||||||
|
|
||||||
<form class="Box str mobcol" action="<?= e(url('network_set')) ?>" method="GET" id="form-2">
|
|
||||||
<h2 tabindex=0><?= tr('net.sta') ?></h2>
|
|
||||||
|
|
||||||
<div class="Row explain">
|
|
||||||
<?= tr('net.explain_sta') ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row checkbox x-static-toggle" >
|
|
||||||
<label><?= tr('net.sta_dhcp_enable') ?></label><!--
|
|
||||||
--><span class="box" tabindex=0 role=checkbox></span>
|
|
||||||
<input type="hidden" id="sta_dhcp_enable" name="sta_dhcp_enable" value="%sta_dhcp_enable%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row x-static">
|
|
||||||
<label for="sta_addr_ip"><?= tr('net.sta_addr_ip') ?></label>
|
|
||||||
<input type="text" name="sta_addr_ip" id="sta_addr_ip" value="%h:sta_addr_ip%" <?=$ipmask?> required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row x-static">
|
|
||||||
<label for="sta_addr_mask"><?= tr('net.sta_addr_mask') ?></label>
|
|
||||||
<input type="text" name="sta_addr_mask" id="sta_addr_mask" value="%h:sta_addr_mask%" <?=$ipmask?> required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row x-static">
|
|
||||||
<label for="sta_addr_gw"><?= tr('net.sta_addr_gw') ?></label>
|
|
||||||
<input type="text" name="sta_addr_gw" id="sta_addr_gw" value="%h:sta_addr_gw%" <?=$ipmask?> required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons">
|
|
||||||
<a class="button icn-ok" href="#" onclick="qs('#form-2').submit()"><?= tr('apply') ?></a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form class="Box str mobcol" action="<?= e(url('network_set')) ?>" method="GET" id="form-1">
|
|
||||||
<h2 tabindex=0><?= tr('net.ap') ?></h2>
|
|
||||||
|
|
||||||
<div class="Row explain">
|
|
||||||
<?= tr('net.explain_ap') ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="ap_addr_mask"><?= tr('net.ap_addr_mask') ?></label>
|
|
||||||
<input type="text" name="ap_addr_mask" id="ap_addr_mask" value="%h:ap_addr_mask%" <?=$ipmask?> required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="ap_addr_ip"><?= tr('net.ap_addr_ip') ?></label>
|
|
||||||
<input type="text" name="ap_addr_ip" id="ap_addr_ip" value="%h:ap_addr_ip%" <?=$ipmask?> required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="ap_dhcp_start"><?= tr('net.ap_dhcp_start') ?></label>
|
|
||||||
<input type="text" name="ap_dhcp_start" id="ap_dhcp_start" value="%h:ap_dhcp_start%" <?=$ipmask?> required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="ap_dhcp_end"><?= tr('net.ap_dhcp_end') ?></label>
|
|
||||||
<input type="text" name="ap_dhcp_end" id="ap_dhcp_end" value="%h:ap_dhcp_end%" <?=$ipmask?> required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="ap_dhcp_time"><?= tr('net.ap_dhcp_time') ?><span class="mq-phone"> (min)</span></label>
|
|
||||||
<input type="number" step=1 min=1 max=2880 name="ap_dhcp_time" id="ap_dhcp_time" value="%ap_dhcp_time%" required>
|
|
||||||
<span class="mq-no-phone"> min</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons">
|
|
||||||
<a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="Box mobcol">
|
|
||||||
<h2><?= tr('net.details') ?></h2>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label><?= tr('net.sta_mac') ?></label><input type="text" readonly value="%sta_mac%">
|
|
||||||
</div>
|
|
||||||
<div class="Row">
|
|
||||||
<label><?= tr('net.ap_mac') ?></label><input type="text" readonly value="%ap_mac%">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function updateStaticDisp() {
|
|
||||||
var sttc = !parseInt($('#sta_dhcp_enable').val());
|
|
||||||
$('.x-static').toggleClass('hidden', !sttc);
|
|
||||||
}
|
|
||||||
$('.x-static-toggle').on('click', function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
updateStaticDisp();
|
|
||||||
}, 0)
|
|
||||||
});
|
|
||||||
updateStaticDisp();
|
|
||||||
</script>
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
<div class="Box str mobcol">
|
|
||||||
<h2 tabindex=0><?= tr('system.save_restore') ?></h2>
|
|
||||||
|
|
||||||
<div class="Row explain nomargintop">
|
|
||||||
<?= tr('system.explain_persist') ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons2">
|
|
||||||
<a class="button icn-restore"
|
|
||||||
onclick="return confirm('<?= tr('system.confirm_restore') ?>');"
|
|
||||||
href="<?= e(url('restore_defaults')) ?>">
|
|
||||||
<?= tr('system.restore_defaults') ?>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons2">
|
|
||||||
<a onclick="writeDefaults(); return false;" href="#"><?= tr('system.write_defaults') ?></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons2">
|
|
||||||
<a onclick="return confirm('<?= tr('system.confirm_restore_hard') ?>');"
|
|
||||||
href="<?= e(url('restore_hard')) ?>">
|
|
||||||
<?= tr('system.restore_hard') ?>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<form class="Box str mobcol" action="<?= e(url('system_set')) ?>" method="GET" id="form-1">
|
|
||||||
<h2 tabindex=0><?= tr('system.uart') ?></h2>
|
|
||||||
|
|
||||||
<div class="Row explain">
|
|
||||||
<?= tr('system.explain_uart') ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="uart_baud"><?= tr('uart.baud') ?><span class="mq-phone"> (bps)</span></label>
|
|
||||||
<select name="uart_baud" id="uart_baud" class="short">
|
|
||||||
<?php foreach([
|
|
||||||
300, 600, 1200, 2400, 4800, 9600, 19200, 38400,
|
|
||||||
57600, 74880, 115200, 230400, 460800, 921600, 1843200, 3686400,
|
|
||||||
] as $b):
|
|
||||||
?><option value="<?=$b?>"><?= number_format($b, 0, ',', '.') ?></option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
<span class="mq-no-phone"> bps</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="uart_parity"><?= tr('uart.parity') ?></label>
|
|
||||||
<select name="uart_parity" id="uart_parity" class="short">
|
|
||||||
<?php foreach([
|
|
||||||
2 => tr('uart.parity.none'),
|
|
||||||
1 => tr('uart.parity.odd'),
|
|
||||||
0 => tr('uart.parity.even'),
|
|
||||||
] as $k => $label):
|
|
||||||
?><option value="<?=$k?>"><?=$label?></option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="uart_stopbits"><?= tr('uart.stop_bits') ?></label>
|
|
||||||
<select name="uart_stopbits" id="uart_stopbits" class="short">
|
|
||||||
<?php foreach([
|
|
||||||
1 => tr('uart.stop_bits.one'),
|
|
||||||
2 => tr('uart.stop_bits.one_and_half'),
|
|
||||||
3 => tr('uart.stop_bits.two'),
|
|
||||||
] as $k => $label):
|
|
||||||
?><option value="<?=$k?>"><?=$label?></option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons">
|
|
||||||
<a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function writeDefaults() {
|
|
||||||
var pw = prompt('<?= tr('system.confirm_store_defaults') ?>');
|
|
||||||
if (!pw) return;
|
|
||||||
location.href = <?=json_encode(url('write_defaults')) ?> + '?pw=' + pw;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#uart_baud').val(%uart_baud%);
|
|
||||||
$('#uart_parity').val(%uart_parity%);
|
|
||||||
$('#uart_stopbits').val(%uart_stopbits%);
|
|
||||||
</script>
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
<div class="Box">
|
|
||||||
<a href="<?= e(url('reset_screen')) ?>"><?= tr('term.reset_screen') ?></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form class="Box mobopen str" action="<?= e(url('term_set')) ?>" method="GET" id='form-1'>
|
|
||||||
<h2><?= tr('term.defaults') ?></h2>
|
|
||||||
|
|
||||||
<div class="Row explain">
|
|
||||||
<?= tr('term.explain_initials') ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="theme"><?= tr("term.theme") ?></label>
|
|
||||||
<select name="theme" id="theme" class="short" onchange="showColor()">
|
|
||||||
<option value="0">Tango</option>
|
|
||||||
<option value="1">Linux</option>
|
|
||||||
<option value="2">XTerm</option>
|
|
||||||
<option value="3">Rxvt</option>
|
|
||||||
<option value="4">Ambience</option>
|
|
||||||
<option value="5">Solarized</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row color-preview">
|
|
||||||
<div class="colorprev">
|
|
||||||
<span data-fg=0 class="bg0 fg0">30</span><!--
|
|
||||||
--><span data-fg=1 class="bg0 fg1">31</span><!--
|
|
||||||
--><span data-fg=2 class="bg0 fg2">32</span><!--
|
|
||||||
--><span data-fg=3 class="bg0 fg3">33</span><!--
|
|
||||||
--><span data-fg=4 class="bg0 fg4">34</span><!--
|
|
||||||
--><span data-fg=5 class="bg0 fg5">35</span><!--
|
|
||||||
--><span data-fg=6 class="bg0 fg6">36</span><!--
|
|
||||||
--><span data-fg=7 class="bg0 fg7">37</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span data-fg=8 class="bg0 fg8">90</span><!--
|
|
||||||
--><span data-fg=9 class="bg0 fg9">91</span><!--
|
|
||||||
--><span data-fg=10 class="bg0 fg10">92</span><!--
|
|
||||||
--><span data-fg=11 class="bg0 fg11">93</span><!--
|
|
||||||
--><span data-fg=12 class="bg0 fg12">94</span><!--
|
|
||||||
--><span data-fg=13 class="bg0 fg13">95</span><!--
|
|
||||||
--><span data-fg=14 class="bg0 fg14">96</span><!--
|
|
||||||
--><span data-fg=15 class="bg0 fg15">97</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span data-bg=0 class="bg0 fg15">40</span><!--
|
|
||||||
--><span data-bg=1 class="bg1 fg15">41</span><!--
|
|
||||||
--><span data-bg=2 class="bg2 fg15">42</span><!--
|
|
||||||
--><span data-bg=3 class="bg3 fg0">43</span><!--
|
|
||||||
--><span data-bg=4 class="bg4 fg15">44</span><!--
|
|
||||||
--><span data-bg=5 class="bg5 fg15">45</span><!--
|
|
||||||
--><span data-bg=6 class="bg6 fg15">46</span><!--
|
|
||||||
--><span data-bg=7 class="bg7 fg0">47</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span data-bg=8 class="bg8 fg15">100</span><!--
|
|
||||||
--><span data-bg=9 class="bg9 fg0">101</span><!--
|
|
||||||
--><span data-bg=10 class="bg10 fg0">102</span><!--
|
|
||||||
--><span data-bg=11 class="bg11 fg0">103</span><!--
|
|
||||||
--><span data-bg=12 class="bg12 fg0">104</span><!--
|
|
||||||
--><span data-bg=13 class="bg13 fg0">105</span><!--
|
|
||||||
--><span data-bg=14 class="bg14 fg0">106</span><!--
|
|
||||||
--><span data-bg=15 class="bg15 fg0">107</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row color-preview">
|
|
||||||
<div style="
|
|
||||||
" id="color-example">
|
|
||||||
<?= tr("term.example") ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label><?= tr("term.default_fg_bg") ?></label>
|
|
||||||
<select name="default_fg" id="default_fg" class="short" onchange="showColor()">
|
|
||||||
<?php for($i=0; $i<16; $i++): ?>
|
|
||||||
<option value="<?=$i?>"><?= tr("color.$i") ?></option>
|
|
||||||
<?php endfor; ?>
|
|
||||||
</select> <!--
|
|
||||||
--><select name="default_bg" id="default_bg" class="short" onchange="showColor()">
|
|
||||||
<?php for($i=0; $i<16; $i++): ?>
|
|
||||||
<option value="<?=$i?>"><?= tr("color.$i") ?></option>
|
|
||||||
<?php endfor; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="term_width"><?= tr('term.term_width') ?></label>
|
|
||||||
<input type="number" step=1 min=1 max=255 name="term_width" id="term_width" value="%term_width%" required> <!--
|
|
||||||
--><input type="number" step=1 min=1 max=255 name="term_height" id="term_height" value="%term_height%" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="term_title"><?= tr('term.term_title') ?></label>
|
|
||||||
<input type="text" name="term_title" id="term_title" value="%h:term_title%" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label><?= tr("term.buttons") ?></label>
|
|
||||||
<input class="short" type="text" name="btn1" id="btn1" value="%h:btn1%">
|
|
||||||
<input class="short" type="text" name="btn2" id="btn2" value="%h:btn2%">
|
|
||||||
<input class="short" type="text" name="btn3" id="btn3" value="%h:btn3%">
|
|
||||||
<input class="short" type="text" name="btn4" id="btn4" value="%h:btn4%">
|
|
||||||
<input class="short" type="text" name="btn5" id="btn5" value="%h:btn5%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons">
|
|
||||||
<a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form class="Box fold str" action="<?= e(url('term_set')) ?>" method="GET" id='form-2'>
|
|
||||||
<h2><?= tr('term.expert') ?></h2>
|
|
||||||
|
|
||||||
<div class="Row explain">
|
|
||||||
<?= tr('term.explain_expert') ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="parser_tout_ms"><?= tr('term.parser_tout_ms') ?><span class="mq-phone"> (ms)</span></label>
|
|
||||||
<input type="number" step=1 min=0 name="parser_tout_ms" id="parser_tout_ms" value="%parser_tout_ms%" required>
|
|
||||||
<span class="mq-no-phone"> ms</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="display_tout_ms"><?= tr('term.display_tout_ms') ?><span class="mq-phone"> (ms)</span></label>
|
|
||||||
<input type="number" step=1 min=0 name="display_tout_ms" id="display_tout_ms" value="%display_tout_ms%" required>
|
|
||||||
<span class="mq-no-phone"> ms</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label for="display_cooldown_ms"><?= tr('term.display_cooldown_ms') ?><span class="mq-phone"> (ms)</span></label>
|
|
||||||
<input type="number" step=1 min=0 name="display_cooldown_ms" id="display_cooldown_ms" value="%display_cooldown_ms%" required>
|
|
||||||
<span class="mq-no-phone"> ms</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row">
|
|
||||||
<label><?= tr("term.button_msgs") ?></label>
|
|
||||||
<input class="short" type="text" name="bm1" id="bm1" value="%h:bm1%">
|
|
||||||
<input class="short" type="text" name="bm2" id="bm2" value="%h:bm2%">
|
|
||||||
<input class="short" type="text" name="bm3" id="bm3" value="%h:bm3%">
|
|
||||||
<input class="short" type="text" name="bm4" id="bm4" value="%h:bm4%">
|
|
||||||
<input class="short" type="text" name="bm5" id="bm5" value="%h:bm5%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row checkbox" >
|
|
||||||
<label><?= tr('term.fn_alt_mode') ?></label><!--
|
|
||||||
--><span class="box" tabindex=0 role=checkbox></span>
|
|
||||||
<input type="hidden" id="fn_alt_mode" name="fn_alt_mode" value="%fn_alt_mode%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row checkbox" >
|
|
||||||
<label><?= tr('term.show_buttons') ?></label><!--
|
|
||||||
--><span class="box" tabindex=0 role=checkbox></span>
|
|
||||||
<input type="hidden" id="show_buttons" name="show_buttons" value="%show_buttons%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row checkbox" >
|
|
||||||
<label><?= tr('term.show_config_links') ?></label><!--
|
|
||||||
--><span class="box" tabindex=0 role=checkbox></span>
|
|
||||||
<input type="hidden" id="show_config_links" name="show_config_links" value="%show_config_links%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row checkbox" >
|
|
||||||
<label><?= tr('term.loopback') ?></label><!--
|
|
||||||
--><span class="box" tabindex=0 role=checkbox></span>
|
|
||||||
<input type="hidden" id="loopback" name="loopback" value="%loopback%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons">
|
|
||||||
<a class="button icn-ok" href="#" onclick="qs('#form-2').submit()"><?= tr('apply') ?></a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$('#default_fg').val(%default_fg%);
|
|
||||||
$('#default_bg').val(%default_bg%);
|
|
||||||
$('#theme').val(%theme%);
|
|
||||||
|
|
||||||
function showColor() {
|
|
||||||
var ex = qs('#color-example');
|
|
||||||
ex.className = '';
|
|
||||||
ex.classList.add('fg'+$('#default_fg').val());
|
|
||||||
ex.classList.add('bg'+$('#default_bg').val());
|
|
||||||
var th = $('#theme').val();
|
|
||||||
$('.color-preview').forEach(function(e) {
|
|
||||||
e.className = 'Row color-preview theme-'+th;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
showColor();
|
|
||||||
|
|
||||||
$('.colorprev span').on('click', function() {
|
|
||||||
var fg = this.dataset.fg;
|
|
||||||
var bg = this.dataset.bg;
|
|
||||||
if (typeof fg != 'undefined') $('#default_fg').val(fg);
|
|
||||||
if (typeof bg != 'undefined') $('#default_bg').val(bg);
|
|
||||||
showColor()
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
<form class="Box str mobcol" action="<?= e(url('wifi_set')) ?>" method="GET" id="form-1">
|
|
||||||
<h2 tabindex=0><?= tr('wifi.ap') ?></h2>
|
|
||||||
|
|
||||||
<div class="Row checkbox x-ap-toggle">
|
|
||||||
<label><?= tr('wifi.enable') ?></label><!--
|
|
||||||
--><span class="box" tabindex=0></span>
|
|
||||||
<input type="hidden" id="ap_enabled" name="ap_enable" value="%ap_enable%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row x-ap-on">
|
|
||||||
<label for="ap_ssid"><?= tr('wifi.ap_ssid') ?></label>
|
|
||||||
<input type="text" name="ap_ssid" id="ap_ssid" value="%h:ap_ssid%" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row x-ap-on">
|
|
||||||
<label for="ap_password"><?= tr('wifi.ap_password') ?></label>
|
|
||||||
<input type="text" name="ap_password" id="ap_password" value="%h:ap_password%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row x-ap-on">
|
|
||||||
<label for="ap_channel"><?= tr('wifi.ap_channel') ?></label>
|
|
||||||
<input type="number" name="ap_channel" id="ap_channel" min=1 max=14 value="%ap_channel%" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row range x-ap-on">
|
|
||||||
<label for="tpw">
|
|
||||||
<?= tr('wifi.tpw') ?>
|
|
||||||
<span class="display x-disp1 mq-phone"></span>
|
|
||||||
</label>
|
|
||||||
<input type="range" name="tpw" id="tpw" step=1 min=0 max=82 value="%tpw%">
|
|
||||||
<span class="display x-disp2 mq-no-phone"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row checkbox x-ap-on">
|
|
||||||
<label><?= tr('wifi.ap_hidden') ?></label><!--
|
|
||||||
--><span class="box" tabindex=0></span>
|
|
||||||
<input type="hidden" name="ap_hidden" value="%ap_hidden%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons">
|
|
||||||
<a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form class="Box str mobcol expanded" action="<?= e(url('wifi_set')) ?>" method="GET" id="form-2">
|
|
||||||
<h2 tabindex=0><?= tr('wifi.sta') ?></h2>
|
|
||||||
|
|
||||||
<div class="Row checkbox x-sta-toggle">
|
|
||||||
<label><?= tr('wifi.enable') ?></label><!--
|
|
||||||
--><span class="box" tabindex=0></span>
|
|
||||||
<input type="hidden" id="sta_enabled" name="sta_enable" value="%sta_enable%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row explain nomargintop x-sta-on">
|
|
||||||
<span class="spacer"></span>
|
|
||||||
<?= tr("wifi.sta_explain") ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input type="hidden" name="sta_ssid" id="sta_ssid" value="">
|
|
||||||
<input type="hidden" name="sta_password" id="sta_password" value="">
|
|
||||||
|
|
||||||
<div class="Row sta-info x-sta-on">
|
|
||||||
<label><?= tr('wifi.sta_info') ?></label>
|
|
||||||
<div class="AP-preview hidden" id="sta-nw">
|
|
||||||
<div class="wrap">
|
|
||||||
<div class="inner">
|
|
||||||
<div class="essid"></div>
|
|
||||||
<div class="passwd"><?= tr('wifi.sta_active_pw') ?></div>
|
|
||||||
<div class="nopasswd"><?= tr('wifi.sta_active_nopw') ?></div>
|
|
||||||
<div class="ip"></div>
|
|
||||||
</div>
|
|
||||||
<a class="forget" href="#" id="forget-sta">×</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="AP-preview-nil" id="sta-nw-nil">
|
|
||||||
<?= tr('wifi.sta_none') ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="ap-box" class="x-sta-on">
|
|
||||||
<label><?= tr('wifi.select_ssid') ?></label>
|
|
||||||
<div id="ap-scan"><a href="#" onclick="WiFi.startScanning(); return false"><?= tr('wifi.scan_now') ?></a></div>
|
|
||||||
<div id="ap-loader" class="hidden"><?= tr('wifi.scanning') ?><span class="anim-dots">.</span></div>
|
|
||||||
<div id="ap-list" class="hidden"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Row buttons">
|
|
||||||
<a class="button icn-ok" href="#" onclick="qs('#form-2').submit()"><?= tr('apply') ?></a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
WiFi.scan_url = '<?= url('wifi_scan', true) ?>';
|
|
||||||
WiFi.init({
|
|
||||||
sta_ssid: '%j:sta_ssid%',
|
|
||||||
sta_password: '%j:sta_password%',
|
|
||||||
sta_active_ip: '%j:sta_active_ip%',
|
|
||||||
sta_active_ssid: '%j:sta_active_ssid%',
|
|
||||||
});
|
|
||||||
|
|
||||||
function updateApDisp() {
|
|
||||||
var a = !!parseInt($('#ap_enabled').val());
|
|
||||||
$('.x-ap-on').toggleClass('hidden', !a);
|
|
||||||
}
|
|
||||||
$('.x-ap-toggle').on('click', function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
updateApDisp();
|
|
||||||
}, 0)
|
|
||||||
});
|
|
||||||
|
|
||||||
function updateStaDisp() {
|
|
||||||
var a = !!parseInt($('#sta_enabled').val());
|
|
||||||
$('.x-sta-on').toggleClass('hidden', !a);
|
|
||||||
}
|
|
||||||
$('.x-sta-toggle').on('click', function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
updateStaDisp();
|
|
||||||
}, 0)
|
|
||||||
});
|
|
||||||
|
|
||||||
updateApDisp();
|
|
||||||
updateStaDisp();
|
|
||||||
</script>
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
<h1><?= tr('menu.cfg_wifi_conn') ?></h1>
|
|
||||||
|
|
||||||
<div class="Box">
|
|
||||||
<p><b><?= tr('wifi.conn.status') ?></b> <span id="status"></span><span class="anim-dots">.</span></p>
|
|
||||||
<a href="<?= e(url('cfg_wifi')) ?>" id="backbtn" class="button"><?= tr('wifi.conn.back_to_config') ?></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box">
|
|
||||||
<p><?= tr('wifi.conn.explain_android_sucks') ?></p>
|
|
||||||
<p><?= tr('wifi.conn.explain_reset') ?></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
var abortTmeo;
|
|
||||||
var failCounter = 0;
|
|
||||||
|
|
||||||
var messages = <?= json_encode([
|
|
||||||
'disabled' => tr('wifi.conn.disabled'),
|
|
||||||
'idle' => tr('wifi.conn.idle'),
|
|
||||||
'success' => tr('wifi.conn.success'),
|
|
||||||
'working' => tr('wifi.conn.working'),
|
|
||||||
'fail' => tr('wifi.conn.fail'),
|
|
||||||
]) ?>;
|
|
||||||
|
|
||||||
function onFail() {
|
|
||||||
$("#status").html(<?= json_encode(tr('wifi.conn.telemetry_lost')) ?>);
|
|
||||||
$('.anim-dots').addClass('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStatus() {
|
|
||||||
xhr.open("GET", 'http://'+_root+'<?= url('wifi_connstatus', true) ?>');
|
|
||||||
xhr.onreadystatechange = function () {
|
|
||||||
if (xhr.readyState == 4) {
|
|
||||||
if (xhr.status == 200) {
|
|
||||||
clearTimeout(abortTmeo);
|
|
||||||
|
|
||||||
try {
|
|
||||||
var data = JSON.parse(xhr.responseText);
|
|
||||||
var done = false;
|
|
||||||
var msg = messages[data.status] || '...';
|
|
||||||
|
|
||||||
if (data.status == 'success') {
|
|
||||||
msg += data.ip;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.status == 'fail') {
|
|
||||||
msg += data.cause;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$("#status").html(msg);
|
|
||||||
|
|
||||||
if (done) {
|
|
||||||
// $('#backbtn').removeClass('hidden');
|
|
||||||
$('.anim-dots').addClass('hidden');
|
|
||||||
} else {
|
|
||||||
// ask again after a short delay
|
|
||||||
window.setTimeout(getStatus, 1000);
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
failCounter++;
|
|
||||||
console.log(e);
|
|
||||||
// repeat
|
|
||||||
if (failCounter > 5) {
|
|
||||||
onFail();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
window.setTimeout(getStatus, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onFail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// XHR timeout
|
|
||||||
abortTmeo = setTimeout(function () {
|
|
||||||
xhr.abort();
|
|
||||||
onFail();
|
|
||||||
}, 4000);
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
getStatus();
|
|
||||||
</script>
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<div class="Box">
|
|
||||||
<a href="#" onclick="hpfold(1);return false">Expand all</a> | <a href="#" onclick="hpfold(0);return false">Collapse all</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php require __DIR__ . "/help/troubleshooting.php"; ?>
|
|
||||||
<?php require __DIR__ . "/help/nomenclature.php"; ?>
|
|
||||||
<?php require __DIR__ . "/help/screen_behavior.php"; ?>
|
|
||||||
<?php require __DIR__ . "/help/input.php"; ?>
|
|
||||||
<?php require __DIR__ . "/help/charsets.php"; ?>
|
|
||||||
<?php require __DIR__ . "/help/sgr_styles.php"; ?>
|
|
||||||
<?php require __DIR__ . "/help/sgr_colors.php"; ?>
|
|
||||||
<?php require __DIR__ . "/help/cmd_cursor.php"; ?>
|
|
||||||
<?php require __DIR__ . "/help/cmd_screen.php"; ?>
|
|
||||||
<?php require __DIR__ . "/help/cmd_system.php"; ?>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function hpfold(yes) {
|
|
||||||
$('.fold').toggleClass('expanded', !!yes);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
<div class="Box fold">
|
|
||||||
<h2>Alternate Character Sets</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
ESPTerm implements Alternate Character Sets as a way to print box drawing characters
|
|
||||||
and special symbols. A character set can change what each received ASCII character
|
|
||||||
is printed as on the screen (eg. "{" is "π" in codepage `0`). The implementation is based
|
|
||||||
on the original VT devices.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Since ESPTerm also supports UTF-8, this feature is the most useful for applications
|
|
||||||
which can't print UTF-8 or already use alternate character sets for historical reasons.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Supported codepages</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>`B` - US ASCII (default)</li>
|
|
||||||
<li>`A` - UK ASCII: # replaced with £</li>
|
|
||||||
<li>`0` - Symbols and basic line drawing (standard DEC alternate character set)</li>
|
|
||||||
<li>`1` - Symbols and advanced line drawing (based on DOS codepage 437, ESPTerm specific)</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
All codepages use codes 32-127, 32 being space. A character with no entry in the active codepage
|
|
||||||
stays unchanged.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$codepages = load_esp_charsets();
|
|
||||||
foreach($codepages as $name => $cp) {
|
|
||||||
echo "<h4>Codepage `$name`</h4>\n";
|
|
||||||
echo '<div class="charset">';
|
|
||||||
foreach($cp as $point) {
|
|
||||||
$dis = $point[1]==$point[2]?' class="none"' : '';
|
|
||||||
echo "<div$dis><span>$point[0]</span><span>$point[1]</span><span>$point[2]</span></div>";
|
|
||||||
}
|
|
||||||
echo '</div>';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<h3>Switching commands</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
There are two character set slots, G0 and G1.
|
|
||||||
Those slots are selected as active using ASCII codes Shift In and Shift Out (those originally served for shifting
|
|
||||||
a red-black typewriter tape). Often only G0 is used for simplicity.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Each slot (G0 and G1) can have a different codepage assigned. G0 and G1 and the active slot number are
|
|
||||||
saved and restored with the cursor and cleared with a screen reset (<code>\ec</code>).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>The following commands are used:</p>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>`\e(<i>x</i>`</td>
|
|
||||||
<td>Set G0 = codepage <i>x</i></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`\e)<i>x</i>`</td>
|
|
||||||
<td>Set G1 = codepage <i>x</i></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>_SO_ (14)</td>
|
|
||||||
<td>Activate G0</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>_SI_ (15)</td>
|
|
||||||
<td>Activate G1</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
<div class="Box fold">
|
|
||||||
<h2>Commands: Cursor Functions</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
The coordinates are 1-based, origin is top left. The cursor can move within the entire screen,
|
|
||||||
or in the active Scrolling Region if Origin Mode is enabled.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>After writing a character, the cursor advances to the right. If it has reached the end of the row,
|
|
||||||
it stays on the same line, but writing the next character makes it jump to the start of the next
|
|
||||||
line first, scrolling up if needed. If Auto-wrap mode is disabled, the cursor never wraps or scrolls
|
|
||||||
the screen.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
*Legend:*
|
|
||||||
Italic letters such as _n_ are ASCII numbers that serve as arguments, separated with a semicolon.
|
|
||||||
If an argument is left out, it's treated as 0 or 1, depending on what makes sense for the command.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Movement</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>A \\
|
|
||||||
\e[<i>n</i>B \\
|
|
||||||
\e[<i>n</i>C \\
|
|
||||||
\e[<i>n</i>D
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Move cursor up (`A`), down (`B`), right (`C`), left (`D`)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>F \\
|
|
||||||
\e[<i>n</i>E
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Go _n_ lines up (`F`) or down (`E`), start of line</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>r</i>d \\
|
|
||||||
\e[<i>c</i>G \\
|
|
||||||
\e[<i>r</i>;<i>c</i>H
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Go to absolute position - row (`d`), column (`G`), or both (`H`). Use `\e[H` to go to 1,1.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[6n`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Query cursor position. Sent back as `\e[<i>r</i>;<i>c</i>R`.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Save / restore</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[s \\
|
|
||||||
\e[u
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Save (`s`) or restore (`u`) cursor position</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e7 \\
|
|
||||||
\e8
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Save (`7`) or restore (`8`) cursor position and attributes</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Scrolling Region</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[<i>a</i>;<i>b</i>r`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Set scrolling region to rows _a_ through _b_ and go to 1,1. By default, the
|
|
||||||
scrolling region spans the entire screen height. The cursor can leave the region using
|
|
||||||
absolute position commands, unless Origin Mode (see below) is active.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[?6h \\
|
|
||||||
\e[?6l
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Enable (`h`) or disable (`l`) Origin Mode and go to 1,1. In Origin Mode, all coordinates
|
|
||||||
are relative to the Scrolling Region and the cursor can't leave the region.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>S \\
|
|
||||||
\e[<i>n</i>T
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Move contents of the Scrolling Region up (`S`) or down (`T`), pad with empty
|
|
||||||
lines of the current background color. This is similar to what happens when AutoWrap
|
|
||||||
is enabled and some text is printed at the very end of the screen.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Tab stops</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\eH`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Set tab stop at the current column. There are, by default, tabs every 8 columns.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>I \\
|
|
||||||
\e[<i>n</i>Z
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Advance (`I`) or go back (`Z`) _n_ tab stops or end/start of line. ASCII _TAB_ (9) is equivalent to <code>\e[1I</code></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[0g \\
|
|
||||||
\e[3g \\
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Clear tab stop at the current column (`0`), or all columns (`3`).</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Other options</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[?7h \\
|
|
||||||
\e[?7l
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Enable (`h`) or disable (`l`) cursor auto-wrap and screen auto-scroll</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[?25h \\
|
|
||||||
\e[?25l
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Show (`h`) or hide (`l`) the cursor</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
<div class="Box fold">
|
|
||||||
<h2>Commands: Screen Functions</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
<b>Legend:</b>
|
|
||||||
Italic letters such as _n_ are ASCII numbers that serve as arguments, separated with a semicolon.
|
|
||||||
If an argument is left out, it's treated as 0 or 1, depending on what makes sense for the command.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[<i>m</i>J`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Clear part of screen. _m_: 0 - from cursor, 1 - to cursor, 2 - all
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[<i>m</i>K`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Erase part of line. _m_: 0 - from cursor, 1 - to cursor, 2 - all
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[<i>n</i>X`</td>
|
|
||||||
<td>
|
|
||||||
Erase _n_ characters in line.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>L \\
|
|
||||||
\e[<i>n</i>M
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Insert (`L`) or delete (`M`) _n_ lines. Following lines are pulled up or pushed down.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>@ \\
|
|
||||||
\e[<i>n</i>P
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Insert (`@`) or delete (`P`) _n_ characters. The rest of the line is pulled left or pushed right.
|
|
||||||
Characters going past the end of line are lost.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
<div class="Box fold">
|
|
||||||
<h2>Commands: System Functions</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
It's possible to dynamically change the screen title text and action button labels.
|
|
||||||
Setting an empty label to a button makes it look disabled. The buttons send ASCII 1-5 when clicked.
|
|
||||||
Those changes are not retained after restart.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>`\ec`</td>
|
|
||||||
<td>
|
|
||||||
Clear screen, reset attributes and cursor.
|
|
||||||
The screen size, title and button labels remain unchanged.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`\e[5n`</td>
|
|
||||||
<td>
|
|
||||||
Query device status, ESPTerm replies with `\e[0n` "device is OK".
|
|
||||||
Can be used to check if the terminal has booted up and is ready to receive commands.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>_CAN_ (24)</td>
|
|
||||||
<td>
|
|
||||||
This ASCII code is not a command, but is sent by ESPTerm when it becomes ready to receive commands.
|
|
||||||
When this code is received on the UART, it means ESPTerm has restarted and is ready. Use this to detect
|
|
||||||
spontaneous restarts which require a full screen repaint.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`\e]0;<i>t</i>\a`</td>
|
|
||||||
<td>Set screen title to _t_ (this is a standard OSC command)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e]<i>80+n</i>;<i>t</i>\a
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Set label for button _n_ = 1-5 (code 81-85) to _t_ - e.g.`\e]81;Yes\a`
|
|
||||||
sets the first button text to "Yes".
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e]<i>90+n</i>;<i>m</i>\a
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Set message for button _n_ = 1-5 (code 81-85) to _m_ - e.g.`\e]94;iv\a`
|
|
||||||
sets the 3rd button to send string "iv" when pressed.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[?800h \\
|
|
||||||
\e[?800l
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Show (`h`) or hide (`l`) action buttons (the blue buttons under the screen).
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[?801h \\
|
|
||||||
\e[?801l
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Show (`h`) or hide (`l`) menu/help links under the screen.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[12h \\
|
|
||||||
\e[12l
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Enable (`h`) or disable (`l`) Send-Receive Mode (SRM).
|
|
||||||
SRM is the opposite of Local Echo, meaning `\e[12h` disables and `\e[12l` enables Local Echo.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`\e[8;<i>r</i>;<i>c</i>t`</td>
|
|
||||||
<td>Set screen size to _r_ rows and _c_ columns (this is a command borrowed from Xterm)</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
|
|
||||||
<div class="Box fold">
|
|
||||||
<h2>User Input: Keyboard, Mouse</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<h3>Keyboard</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The user can input text using their keyboard, or on Android, using the on-screen keyboard which is open using
|
|
||||||
a button beneath the screen. Supported are all printable characters, as well as many control keys, such as arrows, _Ctrl+letters_
|
|
||||||
and function keys. Sequences sent by function keys are based on VT102 and Xterm.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The codes sent by _Home_, _End_, _F1-F4_ and cursor keys are affected by various keyboard modes (_Application Cursor Keys_,
|
|
||||||
_Application Numpad Mode_, _SS3 Fn Keys Mode_). Some can be set in the <a href="<?= url('cfg_term') ?>">Terminal Settings</a>,
|
|
||||||
others via commands.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Here are some examples of control key codes:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead><tr><th>Key</th><th>Code</th><th>Key</th><th>Code</th></tr></thead>
|
|
||||||
<tr>
|
|
||||||
<td>Up</td>
|
|
||||||
<td>`\e[A`,~`\eOA`</td>
|
|
||||||
<td>F1</td>
|
|
||||||
<td>`\eOP`,~`\e[11\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Down</td>
|
|
||||||
<td>`\e[B`,~`\eOB`</td>
|
|
||||||
<td>F2</td>
|
|
||||||
<td>`\eOQ`,~`\e[12\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Right</td>
|
|
||||||
<td>`\e[C`,~`\eOC`</td>
|
|
||||||
<td>F3</td>
|
|
||||||
<td>`\eOR`,~`\e[13\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Left</td>
|
|
||||||
<td>`\e[D`,~`\eOD`</td>
|
|
||||||
<td>F4</td>
|
|
||||||
<td>`\eOS`,~`\e[14\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Home</td>
|
|
||||||
<td>`\eOH`,~`\e[H`,~`\e[1\~`</td>
|
|
||||||
<td>F5</td>
|
|
||||||
<td>`\e[15~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>End</td>
|
|
||||||
<td>`\eOF`,~`\e[F`,~`\e[4\~`</td>
|
|
||||||
<td>F6</td>
|
|
||||||
<td>`\e[17\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Insert</td>
|
|
||||||
<td>`\e[2\~`</td>
|
|
||||||
<td>F7</td>
|
|
||||||
<td>`\e[18\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Delete</td>
|
|
||||||
<td>`\e[3\~`</td>
|
|
||||||
<td>F8</td>
|
|
||||||
<td>`\e[19\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Page Up</td>
|
|
||||||
<td>`\e[5\~`</td>
|
|
||||||
<td>F9</td>
|
|
||||||
<td>`\e[20\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Page Down</td>
|
|
||||||
<td>`\e[6\~`</td>
|
|
||||||
<td>F10</td>
|
|
||||||
<td>`\e[21\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Enter</td>
|
|
||||||
<td>`\r` (13)</td>
|
|
||||||
<td>F11</td>
|
|
||||||
<td>`\e[23\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Ctrl+Enter</td>
|
|
||||||
<td>`\n` (10)</td>
|
|
||||||
<td>F12</td>
|
|
||||||
<td>`\e[24\~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Tab</td>
|
|
||||||
<td>`\t` (9)</td>
|
|
||||||
<td>ESC</td>
|
|
||||||
<td>`\e` (27)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Backspace</td>
|
|
||||||
<td>`\b` (8)</td>
|
|
||||||
<td>Ctrl+A..Z</td>
|
|
||||||
<td>ASCII 1-26</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Action buttons</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The blue buttons under the screen send ASCII codes 1, 2, 3, 4, 5, which incidentally
|
|
||||||
correspond to _Ctrl+A,B,C,D,E_. This choice was made to make button press parsing as simple as possible.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Mouse</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
ESPTerm implements standard mouse tracking modes based on Xterm. Mouse tracking can be used to implement
|
|
||||||
powerful user interactions such as on-screen buttons, draggable sliders or dials, menus etc. ESPTerm's
|
|
||||||
mouse tracking was tested using VTTest and should be compatible with all terminal applications
|
|
||||||
that request mouse tracking.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Mouse can be tracked in different ways; some are easier to parse, others more powerful. The coordinates
|
|
||||||
can also be encoded in different ways. All mouse tracking options are set using option commands:
|
|
||||||
`CSI ? _n_ h` to enable, `CSI ? _n_ l` to disable option _n_.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Mouse Tracking Modes</h4>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
All tracking modes produce three numbers which are then encoded and send to the application.
|
|
||||||
First is the _event number_ N, then the _X and Y coordinates_, 1-based.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Mouse buttons are numbered: 1=left, 2=middle, 3=right.
|
|
||||||
Wheel works as two buttons (4 and 5) which generate only press events (no release).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="tscroll">
|
|
||||||
<table class="nomen">
|
|
||||||
<thead><tr><th>Option</th><th>Name</th><th>Description</th></tr></thead>
|
|
||||||
<tr>
|
|
||||||
<td>`9`</td>
|
|
||||||
<td>*X10~mode*</td>
|
|
||||||
<td>
|
|
||||||
This is the most basic tracking mode, in which <b>only button presses</b> are reported.
|
|
||||||
N = button - 1: (0 left, 1 middle, 2 right, 3, 4 wheel).
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1000`</td>
|
|
||||||
<td>*Normal~mode*</td>
|
|
||||||
<td>
|
|
||||||
In Normal mode, both button presses and releases are reported.
|
|
||||||
The lower two bits of N indicate the button pressed:
|
|
||||||
`00b` (0) left, `01b` (1) middle, `10b` (2) right, `11b` (3) button release.
|
|
||||||
Wheel buttons are reported as 0 and 1 with added 64 (e.g. 64 and 65).
|
|
||||||
Normal mode also supports tracking of modifier keys, which are added to N as bit masks:
|
|
||||||
4=_Shift_, 8=_Meta/Alt_, 16=_Control/Cmd_. Example: middle button with _Shift_ = 1 + 4 = `101b` (5).
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1002`</td>
|
|
||||||
<td>*Button-Event tracking*</td>
|
|
||||||
<td>
|
|
||||||
This is similar to Normal mode (`1000`), but mouse motion with a button held is also reported.
|
|
||||||
A motion event is generated when the mouse cursor moves between screen character cells.
|
|
||||||
A motion event has the same N as a press event, but 32 is added.
|
|
||||||
For example, drag-drop event with the middle button will produce N = 1 (press), 33 (dragging) and 3 (release).
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1003`</td>
|
|
||||||
<td>*Any-Event tracking*</td>
|
|
||||||
<td>
|
|
||||||
This mode is almost identical to Button Event tracking (1002), but motion events
|
|
||||||
are sent even when no mouse buttons are held. This could be used to draw on-screen mouse cursor, for example.
|
|
||||||
Motion events with no buttons will use N = 32 + _11b_ (35).
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1004`</td>
|
|
||||||
<td>*Focus~tracking*</td>
|
|
||||||
<td>
|
|
||||||
Focus tracking is a separate function from the other mouse tracking modes, therefore they can be enabled together.
|
|
||||||
Focus tracking reports when the terminal window (in Xterm) gets or loses focus, or in ESPTerm's case, when any
|
|
||||||
user is connected. This can be used to pause/resume a game or on-screen animations.
|
|
||||||
Focus tracking mode sends `CSI I` when the terminal receives, and `CSI O` when it loses focus.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4>Mouse Report Encoding</h4>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The following encoding schemes can be used with any of the tracking modes (except Focus tracking, which is not affected).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="tscroll">
|
|
||||||
<table class="nomen">
|
|
||||||
<thead><tr><th>Option</th><th>Name</th><th>Description</th></tr></thead>
|
|
||||||
<tr>
|
|
||||||
<td>--</td>
|
|
||||||
<td>*Normal~encoding*</td>
|
|
||||||
<td>
|
|
||||||
This is the default encoding scheme used when no other option is selected.
|
|
||||||
In this mode, a mouse report has the format `CSI M _n_ _x_ _y_`,
|
|
||||||
where _n_, _x_ and _y_ are characters with ASCII value = 32 (space) + the respective number, e.g.
|
|
||||||
0 becomes 32 (space), 1 becomes 33 (!). The reason for adding 32 is to avoid producing control characters.
|
|
||||||
Example: `\e[M !!` - left button press at coordinates 1,1 when using X10 mode.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1005`</td>
|
|
||||||
<td>*UTF-8~encoding*</td>
|
|
||||||
<td>
|
|
||||||
This scheme should encode each of the numbers as a UTF-8 code point, expanding the maximum possible value.
|
|
||||||
Since ESPTerm's screen size is limited and this has no practical benefit, this serves simply as an alias
|
|
||||||
to the normal scheme.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1006`</td>
|
|
||||||
<td>*SGR~encoding*</td>
|
|
||||||
<td>
|
|
||||||
In SGR encoding, the response looks like a SGR sequence with the three numbers as semicolon-separated
|
|
||||||
ASCII values. In this case 32 is not added like in the Normal and UTF-8 schemes, because
|
|
||||||
it would serve nor purpose here. Also, button release is not reported as 11b,
|
|
||||||
but using the normal button code while changing the final SGR character: `M` for button press
|
|
||||||
and `m` for button release. Example: `\e[2;80;24m` - the right button was released
|
|
||||||
at row 80, column 24.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1015`</td>
|
|
||||||
<td>*URXVT~encoding*</td>
|
|
||||||
<td>
|
|
||||||
This is similar to SGR encoding, but the final character is always `M` and the numbers are
|
|
||||||
like in the Normal scheme, with 32 added. This scheme has no real advantage over the previous schemes and
|
|
||||||
was added solely for completeness.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
<div class="Box fold">
|
|
||||||
<h2>Basic Intro & Nomenclature</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<img src="/img/vt100.jpg" class="aside" alt="VT102">
|
|
||||||
|
|
||||||
<p>
|
|
||||||
ESPTerm emulates VT102 (pictured) with some additions from later VT models and Xterm.
|
|
||||||
All commonly used attributes and commands are supported.
|
|
||||||
ESPTerm is capable of displaying ncurses applications such as _Midnight Commander_ using _agetty_.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
ESPTerm accepts UTF-8 characters received on the communication UART and displays them on the screen,
|
|
||||||
interpreting some codes as Control Characters. Those are e.g. _Carriage Return_ (13), _Line Feed_ (10),
|
|
||||||
_Tab_ (9), _Backspace_ (8) and _Bell_ (7).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Escape sequences start with the control character _ESC_ (27),
|
|
||||||
followed by any number of ASCII characters forming the body of the command.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Nomenclature & Command Types</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Examples on this help page use the following symbols for special characters and command types:\\
|
|
||||||
(spaces are for clarity only, _DO NOT_ include them in the commands!)
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="tscroll">
|
|
||||||
<table class="nomen">
|
|
||||||
<thead><tr><th>Name</th><th>Symbol</th><th>ASCII</th><th>C string</th><th>Function</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>*ESC*</td>
|
|
||||||
<td>`\e`</td>
|
|
||||||
<td>`ESC` (27)</td>
|
|
||||||
<td>`"\e"`, `"\x1b"`, `"\033"`</td>
|
|
||||||
<td>Introduces an escape sequence. _(Note: `\e` is a GCC extension)_</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*Bell*</td>
|
|
||||||
<td>`\a`</td>
|
|
||||||
<td>`BEL`~(7)</td>
|
|
||||||
<td>`"\a"`, `"\x7"`, `"\07"`</td>
|
|
||||||
<td>Audible beep</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*String Terminator*</td>
|
|
||||||
<td>`ST`</td>
|
|
||||||
<td>`ESC \`~(27~92)<br>_or_~`\a`~(7)</td>
|
|
||||||
<td>`"\x1b\\"`, `"\a"`</td>
|
|
||||||
<td>Terminates a string command (`\a` can be used as an alternative)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*Control Sequence Introducer*</td>
|
|
||||||
<td>`CSI`</td>
|
|
||||||
<td>`ESC [`</td>
|
|
||||||
<td>`"\x1b["`</td>
|
|
||||||
<td>Starts a CSI command. Examples: `\e[?7;10h`, `\e[2J`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*Operating System Command*</td>
|
|
||||||
<td>`OSC`</td>
|
|
||||||
<td>`ESC ]`</td>
|
|
||||||
<td>`"\x1b]"`</td>
|
|
||||||
<td>Starts an OSC command. Is followed by a command string terminated by `ST`. Example: `\e]0;My Screen Title\a`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*Select Graphic Rendition*</td>
|
|
||||||
<td>`SGR`</td>
|
|
||||||
<td>`CSI <i>n</i>;<i>n</i>;<i>n</i>m`</td>
|
|
||||||
<td>`"\x1b[1;2;3m"`</td>
|
|
||||||
<td>Set text attributes, like color or style. 0 to 10 numbers can be used, `\e[m` is treated as `\e[0m`</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>There are also some other commands that don't follow the CSI, SGR or OSC pattern, such as `\e7` or
|
|
||||||
`\e#8`. A list of the most important escape sequences is presented in the following sections.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<div class="Box fold">
|
|
||||||
<h2>Screen Behavior & Refreshing</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
The initial screen size, title text and button labels can be configured in <a href="<?= url('cfg_term') ?>">Terminal Settings</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Screen updates are sent to the browser through a WebSocket after some time of inactivity on the communication UART
|
|
||||||
(called "Redraw Delay"). After an update is sent, at least a time of "Redraw Cooldown" must elapse before the next
|
|
||||||
update can be sent. Those delays are used is to avoid burdening the server with tiny updates during a large screen
|
|
||||||
repaint. If you experience issues (broken image due to dropped bytes), try adjusting those config options. It may also
|
|
||||||
be useful to try different baud rates.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
|
|
||||||
<div class="Box fold theme-0">
|
|
||||||
<h2>Commands: Color SGR</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
Colors are set using SGR commands (like `\e[10;20;30m`). The following tables list the SGR codes to use.
|
|
||||||
Selected colors are used for any new text entered, as well as for empty space when using line and screen clearing commands.
|
|
||||||
The configured default colors can be restored using SGR 39 for foreground and SGR 49 for background.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The actual color representation depends on a color theme which
|
|
||||||
can be selected in <a href="<?= url('cfg_term') ?>">Terminal Settings</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Foreground colors</h3>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span class="bg7 fg0">30</span>
|
|
||||||
<span class="bg0 fg1">31</span>
|
|
||||||
<span class="bg0 fg2">32</span>
|
|
||||||
<span class="bg0 fg3">33</span>
|
|
||||||
<span class="bg0 fg4">34</span>
|
|
||||||
<span class="bg0 fg5">35</span>
|
|
||||||
<span class="bg0 fg6">36</span>
|
|
||||||
<span class="bg0 fg7">37</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span class="bg0 fg8">90</span>
|
|
||||||
<span class="bg0 fg9">91</span>
|
|
||||||
<span class="bg0 fg10">92</span>
|
|
||||||
<span class="bg0 fg11">93</span>
|
|
||||||
<span class="bg0 fg12">94</span>
|
|
||||||
<span class="bg0 fg13">95</span>
|
|
||||||
<span class="bg0 fg14">96</span>
|
|
||||||
<span class="bg0 fg15">97</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>Background colors</h3>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span class="bg0 fg15">40</span>
|
|
||||||
<span class="bg1 fg15">41</span>
|
|
||||||
<span class="bg2 fg15">42</span>
|
|
||||||
<span class="bg3 fg0">43</span>
|
|
||||||
<span class="bg4 fg15">44</span>
|
|
||||||
<span class="bg5 fg15">45</span>
|
|
||||||
<span class="bg6 fg15">46</span>
|
|
||||||
<span class="bg7 fg0">47</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span class="bg8 fg15">100</span>
|
|
||||||
<span class="bg9 fg0">101</span>
|
|
||||||
<span class="bg10 fg0">102</span>
|
|
||||||
<span class="bg11 fg0">103</span>
|
|
||||||
<span class="bg12 fg0">104</span>
|
|
||||||
<span class="bg13 fg0">105</span>
|
|
||||||
<span class="bg14 fg0">106</span>
|
|
||||||
<span class="bg15 fg0">107</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<div class="Box fold">
|
|
||||||
<h2>Commands: Style SGR</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
All text attributes are set using SGR commands like `\e[10;20;30m`, with up to 10 numbers separated by semicolons.
|
|
||||||
To restore all attributes to their default states, use SGR 0: `\e[0m` or `\e[m`.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>Those are the supported text attributes SGR codes:</p>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead><tr><th>Style</th><th>Enable</th><th>Disable</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr><td><b>Bold</b></td><td>1</td><td>21, 22</td></tr>
|
|
||||||
<tr><td style="opacity:.6">Faint</td><td>2</td><td>22</td></tr>
|
|
||||||
<tr><td><i>Italic</i></td><td>3</td><td>23</td></tr>
|
|
||||||
<tr><td><u>Underlined</u></td><td>4</td><td>24</td></tr>
|
|
||||||
<tr><td>Blink</td><td>5</td><td>25</td></tr>
|
|
||||||
<tr><td><span style="color:black;background:#ccc;">Inverse</span></td><td>7</td><td>27</td></tr>
|
|
||||||
<tr><td><s>Striked</s></td><td>9</td><td>29</td></tr>
|
|
||||||
<tr><td>𝔉𝔯𝔞𝔨𝔱𝔲𝔯</td><td>20</td><td>23</td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
<div class="Box fold">
|
|
||||||
<h2>Tips & Troubleshooting</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<ul>
|
|
||||||
<li>*Communication UART (Rx, Tx)* can be configured in the <a href="<?= url('cfg_system') ?>">System Settings</a>.
|
|
||||||
|
|
||||||
<li>*Boot log and debug messages* are available on pin *GPIO2* (P2) at 115200\,baud, 1 stop bit, no parity.
|
|
||||||
Those messages may be disabled through compile flags.
|
|
||||||
|
|
||||||
<li>*Loopback test*: Connect the Rx and Tx pins with a piece of wire. Anything you type in the browser should
|
|
||||||
appear on the screen. Set _Parser Timeout = 0_ in <a href="<?= url('cfg_term') ?>">Terminal Settings</a>
|
|
||||||
to be able to manually enter escape sequences.
|
|
||||||
|
|
||||||
<li>There is very little RAM available to the webserver, and it can support at most 4 connections at the same time.
|
|
||||||
Each terminal session (open window with the terminal screen) uses one persistent connection for screen updates.
|
|
||||||
*Avoid leaving unused windows open*, or either the RAM or connections may be exhausted.
|
|
||||||
|
|
||||||
<li>*For best performance*, use the module in Client mode (connected to external network) and minimize the number
|
|
||||||
of simultaneous connections. Enabling AP consumes extra RAM because the DHCP server and Captive Portal
|
|
||||||
DNS server are started.
|
|
||||||
|
|
||||||
<li>In AP mode, *check that the WiFi channel used is clear*; interference may cause flaky connection.
|
|
||||||
A good mobile app to use for this is
|
|
||||||
<a href="https://play.google.com/store/apps/details?id=com.farproc.wifi.analyzer">WiFi Analyzer (Google Play)</a>.
|
|
||||||
Adjust the hotspot strength and range using the _Tx Power setting_.
|
|
||||||
|
|
||||||
<li>Hold the BOOT button (GPIO0 to GND) for ~1 second to force enable AP. Hold it for ~6 seconds to restore default settings.
|
|
||||||
(This is indicated by the blue LED rapidly flashing). Default settings can be overwritten in the
|
|
||||||
<a href="<?= url('cfg_system') ?>">System Settings</a>.
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
<script>
|
|
||||||
// Workaround for badly loaded page
|
|
||||||
setTimeout(function() {
|
|
||||||
if (typeof termInit == 'undefined' || typeof $ == 'undefined') {
|
|
||||||
console.error("Page load failed, refreshing…");
|
|
||||||
location.reload(true);
|
|
||||||
}
|
|
||||||
}, 3000);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="Modal light hidden" id="fu_modal">
|
|
||||||
<div id="fu_form" class="Dialog">
|
|
||||||
<div class="fu-content">
|
|
||||||
<h2>Text Upload</h2>
|
|
||||||
<p>
|
|
||||||
<label for="fu_file">Load a text file:</label>
|
|
||||||
<input type="file" id="fu_file" accept="text/*" /><br>
|
|
||||||
<textarea id="fu_text"></textarea>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label for="fu_crlf">Line Endings:</label>
|
|
||||||
<select id="fu_crlf">
|
|
||||||
<option value="CR">CR (Enter key)</option>
|
|
||||||
<option value="CRLF">CR LF (Windows)</option>
|
|
||||||
<option value="LF">LF (Linux)</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label for="fu_delay">Line Delay (ms):</label>
|
|
||||||
<input id="fu_delay" type="number" value=1 min=0>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="fu-buttons">
|
|
||||||
<button onclick="TermUpl.start()" class="icn-ok x-fu-go">Start</button>
|
|
||||||
<button onclick="TermUpl.close()" class="icn-cancel x-fu-cancel">Cancel</button>
|
|
||||||
<i class="fu-prog-box">Upload: <span id="fu_prog"></span></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1><!-- Screen title gets loaded here by JS --></h1>
|
|
||||||
|
|
||||||
<div id="term-wrap">
|
|
||||||
<div id="screen" class="theme-%theme%"></div>
|
|
||||||
|
|
||||||
<div id="action-buttons">
|
|
||||||
<button data-n="1"></button><!--
|
|
||||||
--><button data-n="2"></button><!--
|
|
||||||
--><button data-n="3"></button><!--
|
|
||||||
--><button data-n="4"></button><!--
|
|
||||||
--><button data-n="5"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<textarea id="softkb-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
|
|
||||||
|
|
||||||
<nav id="term-nav">
|
|
||||||
<a href="#" onclick="kbOpen(true);return false" class="mq-tablet-max"><i class="icn-keyboard"></i><span><?= tr('term_nav.keybd') ?></span></a><!--
|
|
||||||
--><a href="#" onclick="TermUpl.open();return false"><i class="icn-download"></i><span><?= tr('term_nav.upload') ?></a><!--
|
|
||||||
--><a href="<?= url('cfg_term') ?>" class="x-term-conf-btn"><i class="icn-configure"></i><span><?= tr('term_nav.config') ?></span></a><!--
|
|
||||||
--><a href="<?= url('cfg_wifi') ?>" class="x-term-conf-btn"><i class="icn-wifi"></i><span><?= tr('term_nav.wifi') ?></span></a><!--
|
|
||||||
--><a href="<?= url('help') ?>" class="x-term-conf-btn"><i class="icn-help"></i><span><?= tr('term_nav.help') ?></span></a><!--
|
|
||||||
--><a href="<?= url('about') ?>" class="x-term-conf-btn"><i class="icn-about"></i><span><?= tr('term_nav.about') ?></span></a>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
try {
|
|
||||||
window.noAutoShow = true;
|
|
||||||
termInit(); // the screen will be loaded via ajax
|
|
||||||
Screen.load('%j:labels_seq%');
|
|
||||||
|
|
||||||
// auto-clear the input box
|
|
||||||
$('#softkb-input').on('input', function(e) {
|
|
||||||
setTimeout(function(){
|
|
||||||
var str = $('#softkb-input').val();
|
|
||||||
$('#softkb-input').val('');
|
|
||||||
Input.sendString(str);
|
|
||||||
}, 1);
|
|
||||||
});
|
|
||||||
} catch(e) {
|
|
||||||
console.error(e);
|
|
||||||
console.error("Fail, reloading in 3s…");
|
|
||||||
setTimeout(function() {
|
|
||||||
location.reload(true);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function kbOpen(yes) {
|
|
||||||
var i = qs('#softkb-input');
|
|
||||||
if (yes) i.focus();
|
|
||||||
else i.blur();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
// Customize Neat grid
|
|
||||||
|
|
||||||
@import "lib/neat/neat-helpers";
|
|
||||||
|
|
||||||
// optionally change gri settings
|
|
||||||
|
|
||||||
// Define breakpoints
|
|
||||||
$phone: new-breakpoint(max-width 544px);
|
|
||||||
$tablet: new-breakpoint(min-width 545px max-width 1000px);
|
|
||||||
$normal: new-breakpoint(min-width 1001px max-width 1376px);
|
|
||||||
$large: new-breakpoint(min-width 1377px);
|
|
||||||
|
|
||||||
$tablet-max: new-breakpoint(max-width 1000px);
|
|
||||||
$normal-max: new-breakpoint(max-width 1376px);
|
|
||||||
$tablet-min: new-breakpoint(min-width 545px);
|
|
||||||
$normal-min: new-breakpoint(min-width 1001px);
|
|
||||||
@@ -1,439 +0,0 @@
|
|||||||
/* normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. Set default font family to sans-serif.
|
|
||||||
* 2. Prevent iOS and IE text size adjust after device orientation change,
|
|
||||||
* without disabling user zoom.
|
|
||||||
*/
|
|
||||||
|
|
||||||
*, *:before, *:after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
html {
|
|
||||||
font-family: sans-serif; /* 1 */
|
|
||||||
-ms-text-size-adjust: 100%; /* 2 */
|
|
||||||
-webkit-text-size-adjust: 100%; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove default margin.
|
|
||||||
*/
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HTML5 display definitions
|
|
||||||
========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Correct `block` display not defined for any HTML5 element in IE 8/9.
|
|
||||||
* Correct `block` display not defined for `details` or `summary` in IE 10/11
|
|
||||||
* and Firefox.
|
|
||||||
* Correct `block` display not defined for `main` in IE 11.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//article,
|
|
||||||
//aside,
|
|
||||||
//details,
|
|
||||||
//figcaption,
|
|
||||||
figure,
|
|
||||||
//footer,
|
|
||||||
//header,
|
|
||||||
//hgroup,
|
|
||||||
//main,
|
|
||||||
//menu,
|
|
||||||
nav
|
|
||||||
//section,
|
|
||||||
//summary
|
|
||||||
{
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. Correct `inline-block` display not defined in IE 8/9.
|
|
||||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//audio,
|
|
||||||
canvas,
|
|
||||||
progress
|
|
||||||
//video
|
|
||||||
{
|
|
||||||
display: inline-block; /* 1 */
|
|
||||||
vertical-align: baseline; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevent modern browsers from displaying `audio` without controls.
|
|
||||||
* Remove excess height in iOS 5 devices.
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
//audio:not([controls]) {
|
|
||||||
// display: none;
|
|
||||||
// height: 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address `[hidden]` styling not present in IE 8/9/10.
|
|
||||||
* Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
|
|
||||||
*/
|
|
||||||
|
|
||||||
[hidden]
|
|
||||||
//template
|
|
||||||
{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Links
|
|
||||||
========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the gray background color from active links in IE 10.
|
|
||||||
*/
|
|
||||||
|
|
||||||
a {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Improve readability of focused elements when they are also in an
|
|
||||||
* active/hover state.
|
|
||||||
*/
|
|
||||||
|
|
||||||
a:active,
|
|
||||||
a:hover {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Text-level semantics
|
|
||||||
========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//abbr[title] {
|
|
||||||
// border-bottom: 1px dotted;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
|
||||||
*/
|
|
||||||
|
|
||||||
b
|
|
||||||
//strong
|
|
||||||
{
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address styling not present in Safari and Chrome.
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
//dfn {
|
|
||||||
// font-style: italic;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address variable `h1` font-size and margin within `section` and `article`
|
|
||||||
* contexts in Firefox 4+, Safari, and Chrome.
|
|
||||||
*/
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 2em;
|
|
||||||
margin: 0.67em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 2em;
|
|
||||||
margin: 0.67em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address styling not present in IE 8/9.
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
//mark {
|
|
||||||
// background: #ff0;
|
|
||||||
// color: #000;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address inconsistent and variable font size in all browsers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
small {
|
|
||||||
font-size: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
sub,
|
|
||||||
sup {
|
|
||||||
font-size: 75%;
|
|
||||||
line-height: 0;
|
|
||||||
position: relative;
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
sup {
|
|
||||||
top: -0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub {
|
|
||||||
bottom: -0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Embedded content
|
|
||||||
========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove border when inside `a` element in IE 8/9/10.
|
|
||||||
*/
|
|
||||||
|
|
||||||
img {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Correct overflow not hidden in IE 9/10/11.
|
|
||||||
*/
|
|
||||||
|
|
||||||
svg:not(:root) {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Grouping content
|
|
||||||
========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address margin not present in IE 8/9 and Safari.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//figure {
|
|
||||||
// margin: 1em 40px;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address differences between Firefox and other browsers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
hr {
|
|
||||||
box-sizing: content-box;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contain overflow in all browsers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pre {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address odd `em`-unit font size rendering in all browsers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
code,
|
|
||||||
//kbd,
|
|
||||||
pre
|
|
||||||
//samp
|
|
||||||
{
|
|
||||||
font-family: "DejaVu Sans Mono", "Inconsolata", monospace;
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Forms
|
|
||||||
========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Known limitation: by default, Chrome and Safari on OS X allow very limited
|
|
||||||
* styling of `select`, unless a `border` property is set.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. Correct color not being inherited.
|
|
||||||
* Known issue: affects color of disabled elements.
|
|
||||||
* 2. Correct font properties not being inherited.
|
|
||||||
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button,
|
|
||||||
input,
|
|
||||||
//optgroup,
|
|
||||||
select,
|
|
||||||
textarea {
|
|
||||||
color: inherit; /* 1 */
|
|
||||||
font: inherit; /* 2 */
|
|
||||||
margin: 0; /* 3 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address `overflow` set to `hidden` in IE 8/9/10/11.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button {
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
|
||||||
* All other form control elements do not inherit `text-transform` values.
|
|
||||||
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
|
|
||||||
* Correct `select` style inheritance in Firefox.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button,
|
|
||||||
select {
|
|
||||||
text-transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
|
||||||
* and `video` controls.
|
|
||||||
* 2. Correct inability to style clickable `input` types in iOS.
|
|
||||||
* 3. Improve usability and consistency of cursor style between image-type
|
|
||||||
* `input` and others.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button,
|
|
||||||
//html input[type="button"], /* 1 */
|
|
||||||
input[type="reset"],
|
|
||||||
input[type="submit"] {
|
|
||||||
-webkit-appearance: button; /* 2 */
|
|
||||||
cursor: pointer; /* 3 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-set default cursor for disabled elements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button[disabled],
|
|
||||||
html input[disabled] {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove inner padding and border in Firefox 4+.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button::-moz-focus-inner,
|
|
||||||
input::-moz-focus-inner {
|
|
||||||
border: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
|
||||||
* the UA stylesheet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
input {
|
|
||||||
line-height: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* It's recommended that you don't attempt to style these elements.
|
|
||||||
* Firefox's implementation doesn't respect box-sizing, padding, or width.
|
|
||||||
*
|
|
||||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
|
||||||
* 2. Remove excess padding in IE 8/9/10.
|
|
||||||
*/
|
|
||||||
|
|
||||||
input[type="checkbox"],
|
|
||||||
input[type="radio"] {
|
|
||||||
box-sizing: border-box; /* 1 */
|
|
||||||
padding: 0; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
|
|
||||||
* `font-size` values of the `input`, it causes the cursor style of the
|
|
||||||
* decrement button to change from `default` to `text`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//input[type="number"]::-webkit-inner-spin-button,
|
|
||||||
//input[type="number"]::-webkit-outer-spin-button {
|
|
||||||
// height: auto;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
|
||||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
//input[type="search"] {
|
|
||||||
// -webkit-appearance: textfield; /* 1 */
|
|
||||||
// box-sizing: content-box; /* 2 */
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
|
|
||||||
* Safari (but not Chrome) clips the cancel button when the search input has
|
|
||||||
* padding (and `textfield` appearance).
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
//input[type="search"]::-webkit-search-cancel-button,
|
|
||||||
//input[type="search"]::-webkit-search-decoration {
|
|
||||||
// -webkit-appearance: none;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define consistent border, margin, and padding.
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
//fieldset {
|
|
||||||
// border: 1px solid #c0c0c0;
|
|
||||||
// margin: 0 2px;
|
|
||||||
// padding: 0.35em 0.625em 0.75em;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. Correct `color` not being inherited in IE 8/9/10/11.
|
|
||||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
legend {
|
|
||||||
border: 0; /* 1 */
|
|
||||||
padding: 0; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove default vertical scrollbar in IE 8/9/10/11.
|
|
||||||
*/
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Don't inherit the `font-weight` (applied by a rule above).
|
|
||||||
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
//optgroup {
|
|
||||||
// font-weight: bold;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/* Tables
|
|
||||||
========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove most spacing between table cells.
|
|
||||||
*/
|
|
||||||
|
|
||||||
table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
// Add a highlight for debugging
|
|
||||||
@mixin highlight($color) {
|
|
||||||
outline: 1px solid $color;
|
|
||||||
background: rgba($color, .05);
|
|
||||||
box-shadow: 0 0 2px 2px rgba($color, .2), inset 0 0 2px 2px rgba($color, .2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ellipsis, but for block elements
|
|
||||||
@mixin block-ellipsis($width: 100%) {
|
|
||||||
display: block;
|
|
||||||
max-width: $width;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
word-wrap: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No margins, padding, borders
|
|
||||||
@mixin naked() {
|
|
||||||
border: 0 none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin translate($x, $y) {
|
|
||||||
@include transform(translate($x, $y));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disallow wrapping
|
|
||||||
@mixin nowrap() {
|
|
||||||
white-space: nowrap;
|
|
||||||
word-wrap: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin click-through() {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disallow text selection
|
|
||||||
@mixin noselect() {
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow text selection
|
|
||||||
@mixin can-select() {
|
|
||||||
-webkit-user-select: text;
|
|
||||||
-moz-user-select: text;
|
|
||||||
-ms-user-select: text;
|
|
||||||
user-select: text;
|
|
||||||
cursor: text;
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
@import "normalize";
|
|
||||||
@import "fontello";
|
|
||||||
@import "lib/bourbon/bourbon";
|
|
||||||
|
|
||||||
@import "grid-settings";
|
|
||||||
@import "lib/neat/neat";
|
|
||||||
|
|
||||||
@import "utils";
|
|
||||||
|
|
||||||
$form-label-w: 160px;
|
|
||||||
$form-label-gap: 8px;
|
|
||||||
$form-field-w: 250px;
|
|
||||||
|
|
||||||
$c-red-outline: #ff0099;
|
|
||||||
$c-form-label-fg: white;
|
|
||||||
$c-form-field-bg: #3c3c3c;
|
|
||||||
$c-form-field-fg: white;
|
|
||||||
$c-form-highlight: #2972ba;
|
|
||||||
$c-form-highlight-a: #2ea1f9;
|
|
||||||
|
|
||||||
$c-modal-bg: #242426;
|
|
||||||
|
|
||||||
$screen-stack: "DejaVu Sans Mono", "Liberation Mono", "Inconsolata", monospace;
|
|
||||||
|
|
||||||
@function dist($x) {
|
|
||||||
@return modular-scale($x, 1rem, $golden);
|
|
||||||
}
|
|
||||||
|
|
||||||
@function fsize($x) {
|
|
||||||
@return modular-scale($x, 1em, $major-second);
|
|
||||||
}
|
|
||||||
|
|
||||||
@import "layout/index";
|
|
||||||
@import "form/index";
|
|
||||||
|
|
||||||
// import all our pages
|
|
||||||
@import "pages/wifi";
|
|
||||||
@import "pages/term";
|
|
||||||
@import "pages/about";
|
|
||||||
|
|
||||||
// media queries
|
|
||||||
|
|
||||||
@include media($tablet-min) {
|
|
||||||
.mq-phone { display: none!important; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
.mq-tablet-min, .mq-no-phone { display: none !important; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($normal-min) {
|
|
||||||
.mq-tablet-max { display: none !important; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($tablet-max) {
|
|
||||||
.mq-normal-min { display: none !important; }
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
@import "fancy_button_mixins";
|
|
||||||
|
|
||||||
$btn-gray-f: #DDDDDD;
|
|
||||||
$btn-gray-b: #505050;
|
|
||||||
$btn-gray-l: #343434; // line
|
|
||||||
|
|
||||||
$btn-green-f: #FEFEFE;
|
|
||||||
$btn-green-b: #2ca94b;
|
|
||||||
$btn-green-fa: #FEFEFE;
|
|
||||||
$btn-green-ba: #28ba5c;
|
|
||||||
|
|
||||||
$btn-red-f: #FEFEFE;
|
|
||||||
$btn-red-b: #D04E51;
|
|
||||||
$btn-red-fa: #FEFEFE;
|
|
||||||
$btn-red-ba: #d4403f;
|
|
||||||
|
|
||||||
$btn-blue-f: #FEFEFE;
|
|
||||||
$btn-blue-b: #3983cd;
|
|
||||||
$btn-blue-fa: #FEFEFE;
|
|
||||||
$btn-blue-ba: #2076C6;
|
|
||||||
|
|
||||||
$btn-orange-f: #FEFEFE;
|
|
||||||
$btn-orange-b: #dd8751;
|
|
||||||
$btn-orange-fa: #FEFEFE;
|
|
||||||
$btn-orange-ba: #C6733F;
|
|
||||||
|
|
||||||
button, input[type=submit], .button {
|
|
||||||
@include fancy-btn-base();
|
|
||||||
|
|
||||||
&.narrow {
|
|
||||||
min-width: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
vertical-align: -1px;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
text-shadow: 1.5px 1.5px 2px rgba(black, 0.4);
|
|
||||||
|
|
||||||
@include fancy-btn-colors($btn-blue-f, $btn-blue-b, $btn-blue-fa, $btn-blue-ba);
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline-color: $c-red-outline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//input[type="submit"], .btn-green {
|
|
||||||
// @include fancy-btn-colors($btn-green-f, $btn-green-b, $btn-green-fa, $btn-green-ba);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//.btn-red {
|
|
||||||
// @include fancy-btn-colors($btn-red-f, $btn-red-b, $btn-red-fa, $btn-red-ba);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//.btn-blue {
|
|
||||||
// @include fancy-btn-colors($btn-blue-f, $btn-blue-b, $btn-blue-fa, $btn-blue-ba);
|
|
||||||
//}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
|
|
||||||
// Button styling
|
|
||||||
@mixin fancy-btn-base() {
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 2px;
|
|
||||||
padding: 0 0.6em;
|
|
||||||
border: 0 none;
|
|
||||||
//outline: 0 none !important;
|
|
||||||
line-height: 1.8em;
|
|
||||||
font-size: 1.1em;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
min-width: 5em;
|
|
||||||
|
|
||||||
@include noselect();
|
|
||||||
|
|
||||||
//&[class^="icon-"]::before, &[class*=" icon-"]::before {
|
|
||||||
// margin-left:0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
position: relative;
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
//&, &:active, &:hover, &:visited {
|
|
||||||
// text-decoration: none;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin fancy-btn-colors-full($text_p, $back_p, $side_p, $text_a, $back_a, $side_a) {
|
|
||||||
background-color: $back_p;
|
|
||||||
box-shadow: 0 3px 0 $side_p;
|
|
||||||
text-decoration: none !important;
|
|
||||||
|
|
||||||
&, &:link, &:visited {
|
|
||||||
color: $text_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, &:active, &.active, &.selected {
|
|
||||||
background-color: $back_a;
|
|
||||||
color: $text_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, &.selected, &.active {
|
|
||||||
box-shadow: 0 3px 0 $side_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// thinner shadow
|
|
||||||
&:active {
|
|
||||||
box-shadow: 0 1px 0 $side_a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin fancy-btn-colors($text_p, $back_p, $text_a, $back_a) {
|
|
||||||
@include fancy-btn-colors-full($text_p, $back_p, darken($back_p, 14), $text_a, $back_a, darken($back_a, 16));
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
@import "buttons";
|
|
||||||
|
|
||||||
#{$all-text-inputs}, select, label.select-wrap {
|
|
||||||
width: $form-field-w;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="number"], input.short, select.short {
|
|
||||||
width: $form-field-w/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
#{$all-text-inputs}, select {
|
|
||||||
border: 0 none;
|
|
||||||
border-bottom: 2px solid $c-form-highlight;
|
|
||||||
background-color: $c-form-field-bg;
|
|
||||||
color: $c-form-field-fg;
|
|
||||||
padding: 6px;
|
|
||||||
line-height: 1em;
|
|
||||||
//outline: 0 none !important;
|
|
||||||
//-moz-outline: 0 none !important;
|
|
||||||
font-weight: normal;
|
|
||||||
|
|
||||||
&:focus, &:hover {
|
|
||||||
border-bottom-color: $c-form-highlight-a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Row.checkbox {
|
|
||||||
$h: 27px;
|
|
||||||
line-height: $h;
|
|
||||||
|
|
||||||
.box {
|
|
||||||
overflow: hidden;
|
|
||||||
width: $h;
|
|
||||||
height: $h;
|
|
||||||
border: 1px solid #808080;
|
|
||||||
border-radius: 3px;
|
|
||||||
background: $c-form-field-bg;
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
color: $c-form-highlight-a;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
font-family: "fontello";
|
|
||||||
position: absolute;
|
|
||||||
//content: '×';
|
|
||||||
//content: '✓';
|
|
||||||
left: 0; top: 0; right: 0; bottom: 0;
|
|
||||||
line-height: 25px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 20px;
|
|
||||||
vertical-align: middle;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include icon-content('ok');
|
|
||||||
|
|
||||||
&.checked::before {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Row.range {
|
|
||||||
.display {
|
|
||||||
margin-left: 1ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
label .display { font-weight: normal; }
|
|
||||||
}
|
|
||||||
|
|
||||||
//#{$all-text-inputs} {
|
|
||||||
// @include can-select();
|
|
||||||
//}
|
|
||||||
|
|
||||||
//textarea {
|
|
||||||
// font-family: monospace;
|
|
||||||
// line-height: 1.2em;
|
|
||||||
// display: block; // fixes weird bottom margin
|
|
||||||
//}
|
|
||||||
|
|
||||||
//@import "select";
|
|
||||||
@@ -1,204 +0,0 @@
|
|||||||
// Unified Form wrapper
|
|
||||||
form { @include naked(); }
|
|
||||||
|
|
||||||
.Box.errors {
|
|
||||||
.list {
|
|
||||||
color: crimson;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lead {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Row {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin: 12px auto;
|
|
||||||
text-align: left;
|
|
||||||
line-height: 1.35em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.v {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aside {
|
|
||||||
float: right;
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
margin: 0; float: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.spacer {
|
|
||||||
width: $form-label-w;
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// buttons2 is the same style, but different selector for use in the admin page
|
|
||||||
&.buttons, &.buttons2 {
|
|
||||||
margin: 16px auto;
|
|
||||||
input, .button {
|
|
||||||
margin-right: dist(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.centered {
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.message {
|
|
||||||
font-size: 1em;
|
|
||||||
//margin-left: $label-gap + $w-labels;
|
|
||||||
text-shadow: 1px 1px 3px black;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&.error {
|
|
||||||
color: crimson;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.ok {
|
|
||||||
color: #0fe851;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.separator {
|
|
||||||
padding-top: 14px;
|
|
||||||
border-top: 2px solid rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
min-height: 10rem;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
font-weight: bold;
|
|
||||||
color: $c-form-label-fg;
|
|
||||||
display: inline-block;
|
|
||||||
width: $form-label-w;
|
|
||||||
text-align: right;
|
|
||||||
text-shadow: 1px 1px 3px black;
|
|
||||||
|
|
||||||
padding: $form-label-gap;
|
|
||||||
align-self: flex-start;
|
|
||||||
|
|
||||||
@include noselect;
|
|
||||||
@include nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
label.error {
|
|
||||||
color: crimson;
|
|
||||||
}
|
|
||||||
|
|
||||||
//.checkbox-wrap {
|
|
||||||
// display: inline-block;
|
|
||||||
// width: $form-label-w;
|
|
||||||
// padding: $form-label-gap;
|
|
||||||
// text-align: right;
|
|
||||||
// align-self: flex-start;
|
|
||||||
//
|
|
||||||
// input[type=checkbox] {
|
|
||||||
// margin: auto;
|
|
||||||
// width: auto;
|
|
||||||
// height: auto;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// & + label {
|
|
||||||
// width: $form-field-w;
|
|
||||||
// padding-left: 0;
|
|
||||||
// text-align: left;
|
|
||||||
// cursor: pointer;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
input[type="range"] {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// special phone style
|
|
||||||
@include media($phone) {
|
|
||||||
flex-direction: column;
|
|
||||||
margin: 6px auto;
|
|
||||||
|
|
||||||
&.buttons, &.centered, &.checkbox {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.buttons {
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
// remove margin on lats button
|
|
||||||
:last-child {
|
|
||||||
margin-right:0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
padding-left: 0;
|
|
||||||
text-align: left;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-wrap {
|
|
||||||
order: 1;
|
|
||||||
text-align: left;
|
|
||||||
padding-bottom: 0;
|
|
||||||
|
|
||||||
border-radius: .4px;
|
|
||||||
width: auto;
|
|
||||||
|
|
||||||
& + label {
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#{$all-text-inputs}, input[type="range"], textarea, select {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// red asterisk
|
|
||||||
form span.required {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.RadioGroup {
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 1.5em;
|
|
||||||
vertical-align: middle;
|
|
||||||
|
|
||||||
label {
|
|
||||||
width: auto;
|
|
||||||
text-align: left;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="radio"] {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin: 0 0 0 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
@import 'fancy_button_mixins';
|
|
||||||
@import 'buttons';
|
|
||||||
@import 'form_elements';
|
|
||||||
|
|
||||||
%form-row-spacing {
|
|
||||||
& > * {
|
|
||||||
margin-right: dist(-2);
|
|
||||||
&:last-child { margin-right: 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@import 'form_layout';
|
|
||||||
//@import 'select';
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
|
|
||||||
// target chrome only
|
|
||||||
@media screen and (-webkit-min-device-pixel-ratio: 0) {
|
|
||||||
select { padding-right: 18px }
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
line-height: 1.2em;
|
|
||||||
//padding: 3.5px;
|
|
||||||
|
|
||||||
padding-right: 1em;
|
|
||||||
|
|
||||||
// hack for firefox to disable dotted outline
|
|
||||||
&:-moz-focusring {
|
|
||||||
color: transparent;
|
|
||||||
text-shadow: 0 0 0 $c-form-field-fg;
|
|
||||||
}
|
|
||||||
|
|
||||||
option {
|
|
||||||
background: $c-form-field-bg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
label.select-wrap {
|
|
||||||
position: relative;
|
|
||||||
display: inline !important;
|
|
||||||
margin: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
width: auto !important;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
content: '<>'; /* will be rotated */
|
|
||||||
font-family: "Consolas", monospace;
|
|
||||||
font-weight: bold;
|
|
||||||
color: $c-form-highlight-a;
|
|
||||||
|
|
||||||
top: 50%;
|
|
||||||
@include transform(translate(0, -50%) rotate(90deg));
|
|
||||||
|
|
||||||
right: 2px;
|
|
||||||
|
|
||||||
position:absolute;
|
|
||||||
z-index: 100;
|
|
||||||
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
html {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
color: #D0D0D0;
|
|
||||||
background: #131315;
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
@include naked();
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
a, a:visited, a:link {
|
|
||||||
cursor: pointer;
|
|
||||||
color: #5abfff;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: #5abfff;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
[onclick] {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul > * {
|
|
||||||
padding-top: .3em;
|
|
||||||
padding-bottom: .3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
.botpad {
|
|
||||||
display:block;
|
|
||||||
height: 5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Box {
|
|
||||||
display: block;
|
|
||||||
max-width: 900px;
|
|
||||||
|
|
||||||
margin-top: dist(0);
|
|
||||||
padding: dist(-1) dist(0);
|
|
||||||
|
|
||||||
// clear floats
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
clear: both
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
margin-top: dist(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1, h2 {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 + & {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
p:last-child {
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
border-radius: 3px;
|
|
||||||
background-color: rgba(white, .07);
|
|
||||||
box-shadow: 0 0 4px black;
|
|
||||||
border: 1px solid #4f4f4f;
|
|
||||||
|
|
||||||
&.wide {
|
|
||||||
width: initial;
|
|
||||||
max-width: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.medium {
|
|
||||||
max-width: 1200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
//.Valfield {
|
|
||||||
// display: inline-block;
|
|
||||||
// min-width: 10em;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Submit Top Right
|
|
||||||
&.str {
|
|
||||||
position: relative;
|
|
||||||
.Row.buttons {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
right: dist(0);
|
|
||||||
top: 1.8em;
|
|
||||||
margin: 1rem auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($tablet-min) {
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
margin-top: dist(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.str.mobopen .Row.buttons {
|
|
||||||
top: 0;
|
|
||||||
margin-top: dist(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.Row.explain {
|
|
||||||
display: block; // this stops flex messing up text with inline tags
|
|
||||||
max-width: 600px; margin-left: 0;
|
|
||||||
line-height: 1.2;
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.nomargintop {
|
|
||||||
margin-top: 12px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.padleft {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.mobopen .Row.explain {
|
|
||||||
margin-top: 12px; // default from .Row
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
margin-top: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin mobcol-base {
|
|
||||||
h2 {
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 2px 1.3rem 2px 5px;
|
|
||||||
margin: 0 -5px 0 -5px;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
position: absolute;
|
|
||||||
right: 4px;
|
|
||||||
content: '▸';
|
|
||||||
|
|
||||||
top:50%;
|
|
||||||
font-size: 120%;
|
|
||||||
font-weight: bold;
|
|
||||||
transform: translate(0,-50%) rotate(90deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.expanded h2::after {
|
|
||||||
transform: translate(-25%,-50%) rotate(-90deg);
|
|
||||||
margin-bottom: dist(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.Row {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.expanded {
|
|
||||||
.Row {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
&.v {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Box.fold {
|
|
||||||
@include mobcol-base;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
.Box.fold, .Box.mobcol {
|
|
||||||
h2 {
|
|
||||||
padding: 2px 1.3rem 2px 5px;
|
|
||||||
margin: 0 -5px 0 -5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.expanded h2::after {
|
|
||||||
margin-bottom: dist(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Box.mobcol {
|
|
||||||
@include mobcol-base;
|
|
||||||
|
|
||||||
#ap-box {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.expanded {
|
|
||||||
#ap-box {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
#content {
|
|
||||||
flex-grow: 1;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
padding: dist(0);
|
|
||||||
@include media($phone) {
|
|
||||||
padding: dist(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
text-align: center;
|
|
||||||
font-size: fsize(7);
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: dist(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: fsize(3);
|
|
||||||
margin-bottom: dist(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
h1 {
|
|
||||||
font-size: fsize(5);
|
|
||||||
margin-bottom: dist(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: fsize(2);
|
|
||||||
margin-bottom: dist(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
td, th {
|
|
||||||
padding: dist(-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody th {
|
|
||||||
text-align: right;
|
|
||||||
width: $form-label-w;
|
|
||||||
color: $c-form-label-fg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#content {
|
|
||||||
// fade in effect
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.15s ease-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
#content.load {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
@import "base";
|
|
||||||
|
|
||||||
@import "outer-wrap";
|
|
||||||
@import "menu";
|
|
||||||
@import "content";
|
|
||||||
@import "loader";
|
|
||||||
|
|
||||||
@import "box";
|
|
||||||
@import "modal";
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// Loader wheel in top right corner
|
|
||||||
#loader {
|
|
||||||
position: absolute;
|
|
||||||
right: dist(1);
|
|
||||||
top: dist(1);
|
|
||||||
|
|
||||||
transition: opacity .2s;
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
top: dist(0);
|
|
||||||
right: dist(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.show {
|
|
||||||
opacity:1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
#menu {
|
|
||||||
$menu-bg: #3983CD;
|
|
||||||
$menu-hl: #5badff; //#1bd886;
|
|
||||||
$menu-fg: white;
|
|
||||||
|
|
||||||
flex: 0 0 15rem;
|
|
||||||
background: $menu-bg;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
display: block;
|
|
||||||
text-decoration: none;
|
|
||||||
padding: dist(-1) dist(0);
|
|
||||||
|
|
||||||
@include nowrap;
|
|
||||||
@include noselect;
|
|
||||||
}
|
|
||||||
|
|
||||||
#brand {
|
|
||||||
cursor: pointer;
|
|
||||||
color: $menu-fg;
|
|
||||||
background: darken($menu-bg, 10%);
|
|
||||||
font-size: 120%;
|
|
||||||
text-align: center;
|
|
||||||
position:relative;
|
|
||||||
transition: none;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
margin-bottom: dist(0);
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
background: $menu-bg;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-bottom: dist(-2);
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
position: absolute;
|
|
||||||
color: rgba(black, .4);
|
|
||||||
right: dist(0);
|
|
||||||
content: '▸';
|
|
||||||
|
|
||||||
top:50%;
|
|
||||||
font-size: 120%;
|
|
||||||
font-weight: bold;
|
|
||||||
transform: translate(0,-50%) rotate(90deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.expanded #brand {
|
|
||||||
background: darken($menu-bg, 10%);
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
&:after { transform: translate(-25%,-50%) rotate(-90deg) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-size: 130%;
|
|
||||||
color: $menu-fg;
|
|
||||||
|
|
||||||
transition: background-color 0.2s;
|
|
||||||
text-shadow: 0 0 5px rgba(black, .4);
|
|
||||||
|
|
||||||
&:hover, &.selected {
|
|
||||||
background: $menu-hl;
|
|
||||||
text-shadow: 0 0 5px rgba(black, .6);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
position: relative;
|
|
||||||
box-shadow: 0 0 5px rgba(black, .5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline-color: $c-red-outline;
|
|
||||||
}
|
|
||||||
|
|
||||||
//&::before {
|
|
||||||
// content: "▸";
|
|
||||||
// padding-right: .5rem;
|
|
||||||
// position: relative;
|
|
||||||
// top: -0.1rem;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Fontello
|
|
||||||
&::before {
|
|
||||||
vertical-align: -2px;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
display: none;
|
|
||||||
&::before {margin-left: 10px;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.expanded a { display:block }
|
|
||||||
|
|
||||||
@include media($tablet) {
|
|
||||||
#brand {
|
|
||||||
font-size: 95%;
|
|
||||||
margin-bottom: dist(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
a { font-size: 105%; }
|
|
||||||
|
|
||||||
flex-basis: 10rem;
|
|
||||||
|
|
||||||
& > * { padding: dist(-2) dist(-1); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
.Modal {
|
|
||||||
z-index: 100;
|
|
||||||
position: fixed;
|
|
||||||
width: 100%; height: 100%;
|
|
||||||
left: 0; top: 0; right: 0; bottom: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
transition: opacity .5s;
|
|
||||||
background: rgba(black, .65);
|
|
||||||
opacity: 0;
|
|
||||||
&.visible { opacity: 1 }
|
|
||||||
&.hidden { display: none }
|
|
||||||
|
|
||||||
&.light {
|
|
||||||
background: rgba(black, .25);
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
overflow-y: auto;
|
|
||||||
.Dialog {
|
|
||||||
margin-top: dist(-1) !important;
|
|
||||||
flex-basis: unset;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Dialog {
|
|
||||||
margin: dist(-1);
|
|
||||||
padding: dist(0);
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
//max-width: 100%;
|
|
||||||
//max-height: 100%;
|
|
||||||
flex-basis: 35rem;
|
|
||||||
//min-height: 15rem;
|
|
||||||
|
|
||||||
background: $c-modal-bg;//#1c1c1e;
|
|
||||||
border-left: 6px solid $c-form-highlight;
|
|
||||||
border-right: 6px solid $c-form-highlight;
|
|
||||||
//border-top: 1px solid $c-form-highlight;
|
|
||||||
//border-bottom: 1px solid $c-form-highlight;
|
|
||||||
box-shadow: 0 0 6px 0 black;
|
|
||||||
|
|
||||||
border-radius: 6px;
|
|
||||||
|
|
||||||
h1,h2 {
|
|
||||||
margin-top:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "toast"
|
|
||||||
.NotifyMsg {
|
|
||||||
position: fixed;
|
|
||||||
top: dist(1);
|
|
||||||
right: dist(2);
|
|
||||||
padding: dist(-1) dist(0);
|
|
||||||
|
|
||||||
// center horizontally
|
|
||||||
//left: 50%;
|
|
||||||
//@include translate(-50%,0);
|
|
||||||
// hack to remove blur in chrome
|
|
||||||
-webkit-font-smoothing: subpixel-antialiased;
|
|
||||||
-webkit-transform: translateZ(0) scale(1.0, 1.0);
|
|
||||||
|
|
||||||
background: #3887d0;
|
|
||||||
&.error {
|
|
||||||
background: #d03e42;
|
|
||||||
}
|
|
||||||
|
|
||||||
color: white;
|
|
||||||
text-shadow: 0 0 2px black;
|
|
||||||
box-shadow: 0 0 6px 0 rgba(black, .6);
|
|
||||||
border-radius: 5px;
|
|
||||||
|
|
||||||
max-width: 80%;
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
width: calc(100% - #{dist(0)});
|
|
||||||
}
|
|
||||||
|
|
||||||
transition: opacity .5s;
|
|
||||||
opacity: 0;
|
|
||||||
&.visible { opacity: 1 }
|
|
||||||
&.hidden { display: none }
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
/* Main outer container */
|
|
||||||
#outer {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media($phone) {
|
|
||||||
#outer {
|
|
||||||
display: block;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,411 +0,0 @@
|
|||||||
// The following features have been deprecated and will be removed in the next MAJOR version release
|
|
||||||
|
|
||||||
@mixin inline-block {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
@warn "The inline-block mixin is deprecated and will be removed in the next major version release";
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin button ($style: simple, $base-color: #4294f0, $text-size: inherit, $padding: 7px 18px) {
|
|
||||||
|
|
||||||
@if type-of($style) == string and type-of($base-color) == color {
|
|
||||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if type-of($style) == string and type-of($base-color) == number {
|
|
||||||
$padding: $text-size;
|
|
||||||
$text-size: $base-color;
|
|
||||||
$base-color: #4294f0;
|
|
||||||
|
|
||||||
@if $padding == inherit {
|
|
||||||
$padding: 7px 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if type-of($style) == color and type-of($base-color) == color {
|
|
||||||
$base-color: $style;
|
|
||||||
$style: simple;
|
|
||||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if type-of($style) == color and type-of($base-color) == number {
|
|
||||||
$padding: $text-size;
|
|
||||||
$text-size: $base-color;
|
|
||||||
$base-color: $style;
|
|
||||||
$style: simple;
|
|
||||||
|
|
||||||
@if $padding == inherit {
|
|
||||||
$padding: 7px 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if type-of($style) == number {
|
|
||||||
$padding: $base-color;
|
|
||||||
$text-size: $style;
|
|
||||||
$base-color: #4294f0;
|
|
||||||
$style: simple;
|
|
||||||
|
|
||||||
@if $padding == #4294f0 {
|
|
||||||
$padding: 7px 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
cursor: not-allowed;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
@warn "The button mixin is deprecated and will be removed in the next major version release";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Selector Style Button
|
|
||||||
@mixin buttonstyle($type, $b-color, $t-size, $pad) {
|
|
||||||
// Grayscale button
|
|
||||||
@if $type == simple and $b-color == grayscale($b-color) {
|
|
||||||
@include simple($b-color, true, $t-size, $pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $type == shiny and $b-color == grayscale($b-color) {
|
|
||||||
@include shiny($b-color, true, $t-size, $pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $type == pill and $b-color == grayscale($b-color) {
|
|
||||||
@include pill($b-color, true, $t-size, $pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $type == flat and $b-color == grayscale($b-color) {
|
|
||||||
@include flat($b-color, true, $t-size, $pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Colored button
|
|
||||||
@if $type == simple {
|
|
||||||
@include simple($b-color, false, $t-size, $pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
@else if $type == shiny {
|
|
||||||
@include shiny($b-color, false, $t-size, $pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
@else if $type == pill {
|
|
||||||
@include pill($b-color, false, $t-size, $pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
@else if $type == flat {
|
|
||||||
@include flat($b-color, false, $t-size, $pad);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple Button
|
|
||||||
@mixin simple($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) {
|
|
||||||
$color: hsl(0, 0, 100%);
|
|
||||||
$border: adjust-color($base-color, $saturation: 9%, $lightness: -14%);
|
|
||||||
$inset-shadow: adjust-color($base-color, $saturation: -8%, $lightness: 15%);
|
|
||||||
$stop-gradient: adjust-color($base-color, $saturation: 9%, $lightness: -11%);
|
|
||||||
$text-shadow: adjust-color($base-color, $saturation: 15%, $lightness: -18%);
|
|
||||||
|
|
||||||
@if is-light($base-color) {
|
|
||||||
$color: hsl(0, 0, 20%);
|
|
||||||
$text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$border: grayscale($border);
|
|
||||||
$inset-shadow: grayscale($inset-shadow);
|
|
||||||
$stop-gradient: grayscale($stop-gradient);
|
|
||||||
$text-shadow: grayscale($text-shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
border: 1px solid $border;
|
|
||||||
border-radius: 3px;
|
|
||||||
box-shadow: inset 0 1px 0 0 $inset-shadow;
|
|
||||||
color: $color;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: $textsize;
|
|
||||||
font-weight: bold;
|
|
||||||
@include linear-gradient ($base-color, $stop-gradient);
|
|
||||||
padding: $padding;
|
|
||||||
text-decoration: none;
|
|
||||||
text-shadow: 0 1px 0 $text-shadow;
|
|
||||||
background-clip: padding-box;
|
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
|
||||||
$base-color-hover: adjust-color($base-color, $saturation: -4%, $lightness: -5%);
|
|
||||||
$inset-shadow-hover: adjust-color($base-color, $saturation: -7%, $lightness: 5%);
|
|
||||||
$stop-gradient-hover: adjust-color($base-color, $saturation: 8%, $lightness: -14%);
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$base-color-hover: grayscale($base-color-hover);
|
|
||||||
$inset-shadow-hover: grayscale($inset-shadow-hover);
|
|
||||||
$stop-gradient-hover: grayscale($stop-gradient-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
@include linear-gradient ($base-color-hover, $stop-gradient-hover);
|
|
||||||
|
|
||||||
box-shadow: inset 0 1px 0 0 $inset-shadow-hover;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active:not(:disabled),
|
|
||||||
&:focus:not(:disabled) {
|
|
||||||
$border-active: adjust-color($base-color, $saturation: 9%, $lightness: -14%);
|
|
||||||
$inset-shadow-active: adjust-color($base-color, $saturation: 7%, $lightness: -17%);
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$border-active: grayscale($border-active);
|
|
||||||
$inset-shadow-active: grayscale($inset-shadow-active);
|
|
||||||
}
|
|
||||||
|
|
||||||
border: 1px solid $border-active;
|
|
||||||
box-shadow: inset 0 0 8px 4px $inset-shadow-active, inset 0 0 8px 4px $inset-shadow-active;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shiny Button
|
|
||||||
@mixin shiny($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) {
|
|
||||||
$color: hsl(0, 0, 100%);
|
|
||||||
$border: adjust-color($base-color, $red: -117, $green: -111, $blue: -81);
|
|
||||||
$border-bottom: adjust-color($base-color, $red: -126, $green: -127, $blue: -122);
|
|
||||||
$fourth-stop: adjust-color($base-color, $red: -79, $green: -70, $blue: -46);
|
|
||||||
$inset-shadow: adjust-color($base-color, $red: 37, $green: 29, $blue: 12);
|
|
||||||
$second-stop: adjust-color($base-color, $red: -56, $green: -50, $blue: -33);
|
|
||||||
$text-shadow: adjust-color($base-color, $red: -140, $green: -141, $blue: -114);
|
|
||||||
$third-stop: adjust-color($base-color, $red: -86, $green: -75, $blue: -48);
|
|
||||||
|
|
||||||
@if is-light($base-color) {
|
|
||||||
$color: hsl(0, 0, 20%);
|
|
||||||
$text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$border: grayscale($border);
|
|
||||||
$border-bottom: grayscale($border-bottom);
|
|
||||||
$fourth-stop: grayscale($fourth-stop);
|
|
||||||
$inset-shadow: grayscale($inset-shadow);
|
|
||||||
$second-stop: grayscale($second-stop);
|
|
||||||
$text-shadow: grayscale($text-shadow);
|
|
||||||
$third-stop: grayscale($third-stop);
|
|
||||||
}
|
|
||||||
|
|
||||||
@include linear-gradient(top, $base-color 0%, $second-stop 50%, $third-stop 50%, $fourth-stop 100%);
|
|
||||||
|
|
||||||
border: 1px solid $border;
|
|
||||||
border-bottom: 1px solid $border-bottom;
|
|
||||||
border-radius: 5px;
|
|
||||||
box-shadow: inset 0 1px 0 0 $inset-shadow;
|
|
||||||
color: $color;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: $textsize;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: $padding;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
text-shadow: 0 -1px 1px $text-shadow;
|
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
|
||||||
$first-stop-hover: adjust-color($base-color, $red: -13, $green: -15, $blue: -18);
|
|
||||||
$second-stop-hover: adjust-color($base-color, $red: -66, $green: -62, $blue: -51);
|
|
||||||
$third-stop-hover: adjust-color($base-color, $red: -93, $green: -85, $blue: -66);
|
|
||||||
$fourth-stop-hover: adjust-color($base-color, $red: -86, $green: -80, $blue: -63);
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$first-stop-hover: grayscale($first-stop-hover);
|
|
||||||
$second-stop-hover: grayscale($second-stop-hover);
|
|
||||||
$third-stop-hover: grayscale($third-stop-hover);
|
|
||||||
$fourth-stop-hover: grayscale($fourth-stop-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
@include linear-gradient(top, $first-stop-hover 0%,
|
|
||||||
$second-stop-hover 50%,
|
|
||||||
$third-stop-hover 50%,
|
|
||||||
$fourth-stop-hover 100%);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active:not(:disabled),
|
|
||||||
&:focus:not(:disabled) {
|
|
||||||
$inset-shadow-active: adjust-color($base-color, $red: -111, $green: -116, $blue: -122);
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$inset-shadow-active: grayscale($inset-shadow-active);
|
|
||||||
}
|
|
||||||
|
|
||||||
box-shadow: inset 0 0 20px 0 $inset-shadow-active;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pill Button
|
|
||||||
@mixin pill($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) {
|
|
||||||
$color: hsl(0, 0, 100%);
|
|
||||||
$border-bottom: adjust-color($base-color, $hue: 8, $saturation: -11%, $lightness: -26%);
|
|
||||||
$border-sides: adjust-color($base-color, $hue: 4, $saturation: -21%, $lightness: -21%);
|
|
||||||
$border-top: adjust-color($base-color, $hue: -1, $saturation: -30%, $lightness: -15%);
|
|
||||||
$inset-shadow: adjust-color($base-color, $hue: -1, $saturation: -1%, $lightness: 7%);
|
|
||||||
$stop-gradient: adjust-color($base-color, $hue: 8, $saturation: 14%, $lightness: -10%);
|
|
||||||
$text-shadow: adjust-color($base-color, $hue: 5, $saturation: -19%, $lightness: -15%);
|
|
||||||
|
|
||||||
@if is-light($base-color) {
|
|
||||||
$color: hsl(0, 0, 20%);
|
|
||||||
$text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$border-bottom: grayscale($border-bottom);
|
|
||||||
$border-sides: grayscale($border-sides);
|
|
||||||
$border-top: grayscale($border-top);
|
|
||||||
$inset-shadow: grayscale($inset-shadow);
|
|
||||||
$stop-gradient: grayscale($stop-gradient);
|
|
||||||
$text-shadow: grayscale($text-shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
border: 1px solid $border-top;
|
|
||||||
border-color: $border-top $border-sides $border-bottom;
|
|
||||||
border-radius: 16px;
|
|
||||||
box-shadow: inset 0 1px 0 0 $inset-shadow;
|
|
||||||
color: $color;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: $textsize;
|
|
||||||
font-weight: normal;
|
|
||||||
line-height: 1;
|
|
||||||
@include linear-gradient ($base-color, $stop-gradient);
|
|
||||||
padding: $padding;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
text-shadow: 0 -1px 1px $text-shadow;
|
|
||||||
background-clip: padding-box;
|
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
|
||||||
$base-color-hover: adjust-color($base-color, $lightness: -4.5%);
|
|
||||||
$border-bottom: adjust-color($base-color, $hue: 8, $saturation: 13.5%, $lightness: -32%);
|
|
||||||
$border-sides: adjust-color($base-color, $hue: 4, $saturation: -2%, $lightness: -27%);
|
|
||||||
$border-top: adjust-color($base-color, $hue: -1, $saturation: -17%, $lightness: -21%);
|
|
||||||
$inset-shadow-hover: adjust-color($base-color, $saturation: -1%, $lightness: 3%);
|
|
||||||
$stop-gradient-hover: adjust-color($base-color, $hue: 8, $saturation: -4%, $lightness: -15.5%);
|
|
||||||
$text-shadow-hover: adjust-color($base-color, $hue: 5, $saturation: -5%, $lightness: -22%);
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$base-color-hover: grayscale($base-color-hover);
|
|
||||||
$border-bottom: grayscale($border-bottom);
|
|
||||||
$border-sides: grayscale($border-sides);
|
|
||||||
$border-top: grayscale($border-top);
|
|
||||||
$inset-shadow-hover: grayscale($inset-shadow-hover);
|
|
||||||
$stop-gradient-hover: grayscale($stop-gradient-hover);
|
|
||||||
$text-shadow-hover: grayscale($text-shadow-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
@include linear-gradient ($base-color-hover, $stop-gradient-hover);
|
|
||||||
|
|
||||||
background-clip: padding-box;
|
|
||||||
border: 1px solid $border-top;
|
|
||||||
border-color: $border-top $border-sides $border-bottom;
|
|
||||||
box-shadow: inset 0 1px 0 0 $inset-shadow-hover;
|
|
||||||
cursor: pointer;
|
|
||||||
text-shadow: 0 -1px 1px $text-shadow-hover;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active:not(:disabled),
|
|
||||||
&:focus:not(:disabled) {
|
|
||||||
$active-color: adjust-color($base-color, $hue: 4, $saturation: -12%, $lightness: -10%);
|
|
||||||
$border-active: adjust-color($base-color, $hue: 6, $saturation: -2.5%, $lightness: -30%);
|
|
||||||
$border-bottom-active: adjust-color($base-color, $hue: 11, $saturation: 6%, $lightness: -31%);
|
|
||||||
$inset-shadow-active: adjust-color($base-color, $hue: 9, $saturation: 2%, $lightness: -21.5%);
|
|
||||||
$text-shadow-active: adjust-color($base-color, $hue: 5, $saturation: -12%, $lightness: -21.5%);
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$active-color: grayscale($active-color);
|
|
||||||
$border-active: grayscale($border-active);
|
|
||||||
$border-bottom-active: grayscale($border-bottom-active);
|
|
||||||
$inset-shadow-active: grayscale($inset-shadow-active);
|
|
||||||
$text-shadow-active: grayscale($text-shadow-active);
|
|
||||||
}
|
|
||||||
|
|
||||||
background: $active-color;
|
|
||||||
border: 1px solid $border-active;
|
|
||||||
border-bottom: 1px solid $border-bottom-active;
|
|
||||||
box-shadow: inset 0 0 6px 3px $inset-shadow-active;
|
|
||||||
text-shadow: 0 -1px 1px $text-shadow-active;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flat Button
|
|
||||||
@mixin flat($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) {
|
|
||||||
$color: hsl(0, 0, 100%);
|
|
||||||
|
|
||||||
@if is-light($base-color) {
|
|
||||||
$color: hsl(0, 0, 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
background-color: $base-color;
|
|
||||||
border-radius: 3px;
|
|
||||||
border: 0;
|
|
||||||
color: $color;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: $textsize;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: $padding;
|
|
||||||
text-decoration: none;
|
|
||||||
background-clip: padding-box;
|
|
||||||
|
|
||||||
&:hover:not(:disabled){
|
|
||||||
$base-color-hover: adjust-color($base-color, $saturation: 4%, $lightness: 5%);
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$base-color-hover: grayscale($base-color-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
background-color: $base-color-hover;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active:not(:disabled),
|
|
||||||
&:focus:not(:disabled) {
|
|
||||||
$base-color-active: adjust-color($base-color, $saturation: -4%, $lightness: -5%);
|
|
||||||
|
|
||||||
@if $grayscale == true {
|
|
||||||
$base-color-active: grayscale($base-color-active);
|
|
||||||
}
|
|
||||||
|
|
||||||
background-color: $base-color-active;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flexible grid
|
|
||||||
@function flex-grid($columns, $container-columns: $fg-max-columns) {
|
|
||||||
$width: $columns * $fg-column + ($columns - 1) * $fg-gutter;
|
|
||||||
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
|
|
||||||
@return percentage($width / $container-width);
|
|
||||||
|
|
||||||
@warn "The flex-grid function is deprecated and will be removed in the next major version release";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flexible gutter
|
|
||||||
@function flex-gutter($container-columns: $fg-max-columns, $gutter: $fg-gutter) {
|
|
||||||
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
|
|
||||||
@return percentage($gutter / $container-width);
|
|
||||||
|
|
||||||
@warn "The flex-gutter function is deprecated and will be removed in the next major version release";
|
|
||||||
}
|
|
||||||
|
|
||||||
@function grid-width($n) {
|
|
||||||
@return $n * $gw-column + ($n - 1) * $gw-gutter;
|
|
||||||
|
|
||||||
@warn "The grid-width function is deprecated and will be removed in the next major version release";
|
|
||||||
}
|
|
||||||
|
|
||||||
@function golden-ratio($value, $increment) {
|
|
||||||
@return modular-scale($increment, $value, $ratio: $golden);
|
|
||||||
|
|
||||||
@warn "The golden-ratio function is deprecated and will be removed in the next major version release. Please use the modular-scale function, instead.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin box-sizing($box) {
|
|
||||||
@include prefixer(box-sizing, $box, webkit moz spec);
|
|
||||||
|
|
||||||
@warn "The box-sizing mixin is deprecated and will be removed in the next major version release. This property can now be used un-prefixed.";
|
|
||||||
}
|
|
||||||
-87
@@ -1,87 +0,0 @@
|
|||||||
// Bourbon 4.2.6
|
|
||||||
// http://bourbon.io
|
|
||||||
// Copyright 2011-2015 thoughtbot, inc.
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
@import "settings/prefixer";
|
|
||||||
@import "settings/px-to-em";
|
|
||||||
@import "settings/asset-pipeline";
|
|
||||||
|
|
||||||
@import "functions/assign-inputs";
|
|
||||||
@import "functions/contains";
|
|
||||||
@import "functions/contains-falsy";
|
|
||||||
@import "functions/is-length";
|
|
||||||
@import "functions/is-light";
|
|
||||||
@import "functions/is-number";
|
|
||||||
@import "functions/is-size";
|
|
||||||
@import "functions/px-to-em";
|
|
||||||
@import "functions/px-to-rem";
|
|
||||||
@import "functions/shade";
|
|
||||||
@import "functions/strip-units";
|
|
||||||
@import "functions/tint";
|
|
||||||
@import "functions/transition-property-name";
|
|
||||||
@import "functions/unpack";
|
|
||||||
@import "functions/modular-scale";
|
|
||||||
|
|
||||||
@import "helpers/convert-units";
|
|
||||||
@import "helpers/directional-values";
|
|
||||||
@import "helpers/font-source-declaration";
|
|
||||||
@import "helpers/gradient-positions-parser";
|
|
||||||
@import "helpers/linear-angle-parser";
|
|
||||||
@import "helpers/linear-gradient-parser";
|
|
||||||
@import "helpers/linear-positions-parser";
|
|
||||||
@import "helpers/linear-side-corner-parser";
|
|
||||||
@import "helpers/radial-arg-parser";
|
|
||||||
@import "helpers/radial-positions-parser";
|
|
||||||
@import "helpers/radial-gradient-parser";
|
|
||||||
@import "helpers/render-gradients";
|
|
||||||
@import "helpers/shape-size-stripper";
|
|
||||||
@import "helpers/str-to-num";
|
|
||||||
|
|
||||||
@import "css3/animation";
|
|
||||||
@import "css3/appearance";
|
|
||||||
@import "css3/backface-visibility";
|
|
||||||
@import "css3/background";
|
|
||||||
@import "css3/background-image";
|
|
||||||
@import "css3/border-image";
|
|
||||||
@import "css3/calc";
|
|
||||||
@import "css3/columns";
|
|
||||||
@import "css3/filter";
|
|
||||||
@import "css3/flex-box";
|
|
||||||
@import "css3/font-face";
|
|
||||||
@import "css3/font-feature-settings";
|
|
||||||
@import "css3/hidpi-media-query";
|
|
||||||
@import "css3/hyphens";
|
|
||||||
@import "css3/image-rendering";
|
|
||||||
@import "css3/keyframes";
|
|
||||||
@import "css3/linear-gradient";
|
|
||||||
@import "css3/perspective";
|
|
||||||
@import "css3/placeholder";
|
|
||||||
@import "css3/radial-gradient";
|
|
||||||
@import "css3/selection";
|
|
||||||
@import "css3/text-decoration";
|
|
||||||
@import "css3/transform";
|
|
||||||
@import "css3/transition";
|
|
||||||
@import "css3/user-select";
|
|
||||||
|
|
||||||
@import "addons/border-color";
|
|
||||||
@import "addons/border-radius";
|
|
||||||
@import "addons/border-style";
|
|
||||||
@import "addons/border-width";
|
|
||||||
@import "addons/buttons";
|
|
||||||
@import "addons/clearfix";
|
|
||||||
@import "addons/ellipsis";
|
|
||||||
@import "addons/font-stacks";
|
|
||||||
@import "addons/hide-text";
|
|
||||||
@import "addons/margin";
|
|
||||||
@import "addons/padding";
|
|
||||||
@import "addons/position";
|
|
||||||
@import "addons/prefixer";
|
|
||||||
@import "addons/retina-image";
|
|
||||||
@import "addons/size";
|
|
||||||
@import "addons/text-inputs";
|
|
||||||
@import "addons/timing-functions";
|
|
||||||
@import "addons/triangle";
|
|
||||||
@import "addons/word-wrap";
|
|
||||||
|
|
||||||
@import "bourbon-deprecated-upcoming";
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Provides a quick method for targeting `border-color` on specific sides of a box. Use a `null` value to “skip” a side.
|
|
||||||
///
|
|
||||||
/// @param {Arglist} $vals
|
|
||||||
/// List of arguments
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// .element {
|
|
||||||
/// @include border-color(#a60b55 #76cd9c null #e8ae1a);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// .element {
|
|
||||||
/// border-left-color: #e8ae1a;
|
|
||||||
/// border-right-color: #76cd9c;
|
|
||||||
/// border-top-color: #a60b55;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @require {mixin} directional-property
|
|
||||||
///
|
|
||||||
/// @output `border-color`
|
|
||||||
|
|
||||||
@mixin border-color($vals...) {
|
|
||||||
@include directional-property(border, color, $vals...);
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Provides a quick method for targeting `border-radius` on both corners on the side of a box.
|
|
||||||
///
|
|
||||||
/// @param {Number} $radii
|
|
||||||
/// List of arguments
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// .element-one {
|
|
||||||
/// @include border-top-radius(5px);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// .element-two {
|
|
||||||
/// @include border-left-radius(3px);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// .element-one {
|
|
||||||
/// border-top-left-radius: 5px;
|
|
||||||
/// border-top-right-radius: 5px;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// .element-two {
|
|
||||||
/// border-bottom-left-radius: 3px;
|
|
||||||
/// border-top-left-radius: 3px;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @output `border-radius`
|
|
||||||
|
|
||||||
@mixin border-top-radius($radii) {
|
|
||||||
border-top-left-radius: $radii;
|
|
||||||
border-top-right-radius: $radii;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin border-right-radius($radii) {
|
|
||||||
border-bottom-right-radius: $radii;
|
|
||||||
border-top-right-radius: $radii;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin border-bottom-radius($radii) {
|
|
||||||
border-bottom-left-radius: $radii;
|
|
||||||
border-bottom-right-radius: $radii;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin border-left-radius($radii) {
|
|
||||||
border-bottom-left-radius: $radii;
|
|
||||||
border-top-left-radius: $radii;
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Provides a quick method for targeting `border-style` on specific sides of a box. Use a `null` value to “skip” a side.
|
|
||||||
///
|
|
||||||
/// @param {Arglist} $vals
|
|
||||||
/// List of arguments
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// .element {
|
|
||||||
/// @include border-style(dashed null solid);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// .element {
|
|
||||||
/// border-bottom-style: solid;
|
|
||||||
/// border-top-style: dashed;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @require {mixin} directional-property
|
|
||||||
///
|
|
||||||
/// @output `border-style`
|
|
||||||
|
|
||||||
@mixin border-style($vals...) {
|
|
||||||
@include directional-property(border, style, $vals...);
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Provides a quick method for targeting `border-width` on specific sides of a box. Use a `null` value to “skip” a side.
|
|
||||||
///
|
|
||||||
/// @param {Arglist} $vals
|
|
||||||
/// List of arguments
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// .element {
|
|
||||||
/// @include border-width(1em null 20px);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// .element {
|
|
||||||
/// border-bottom-width: 20px;
|
|
||||||
/// border-top-width: 1em;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @require {mixin} directional-property
|
|
||||||
///
|
|
||||||
/// @output `border-width`
|
|
||||||
|
|
||||||
@mixin border-width($vals...) {
|
|
||||||
@include directional-property(border, width, $vals...);
|
|
||||||
}
|
|
||||||
-64
@@ -1,64 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Generates variables for all buttons. Please note that you must use interpolation on the variable: `#{$all-buttons}`.
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// #{$all-buttons} {
|
|
||||||
/// background-color: #f00;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #{$all-buttons-focus},
|
|
||||||
/// #{$all-buttons-hover} {
|
|
||||||
/// background-color: #0f0;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #{$all-buttons-active} {
|
|
||||||
/// background-color: #00f;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// button,
|
|
||||||
/// input[type="button"],
|
|
||||||
/// input[type="reset"],
|
|
||||||
/// input[type="submit"] {
|
|
||||||
/// background-color: #f00;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// button:focus,
|
|
||||||
/// input[type="button"]:focus,
|
|
||||||
/// input[type="reset"]:focus,
|
|
||||||
/// input[type="submit"]:focus,
|
|
||||||
/// button:hover,
|
|
||||||
/// input[type="button"]:hover,
|
|
||||||
/// input[type="reset"]:hover,
|
|
||||||
/// input[type="submit"]:hover {
|
|
||||||
/// background-color: #0f0;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// button:active,
|
|
||||||
/// input[type="button"]:active,
|
|
||||||
/// input[type="reset"]:active,
|
|
||||||
/// input[type="submit"]:active {
|
|
||||||
/// background-color: #00f;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @require assign-inputs
|
|
||||||
///
|
|
||||||
/// @type List
|
|
||||||
///
|
|
||||||
/// @todo Remove double assigned variables (Lines 59–62) in v5.0.0
|
|
||||||
|
|
||||||
$buttons-list: 'button',
|
|
||||||
'input[type="button"]',
|
|
||||||
'input[type="reset"]',
|
|
||||||
'input[type="submit"]';
|
|
||||||
|
|
||||||
$all-buttons: assign-inputs($buttons-list);
|
|
||||||
$all-buttons-active: assign-inputs($buttons-list, active);
|
|
||||||
$all-buttons-focus: assign-inputs($buttons-list, focus);
|
|
||||||
$all-buttons-hover: assign-inputs($buttons-list, hover);
|
|
||||||
|
|
||||||
$all-button-inputs: $all-buttons;
|
|
||||||
$all-button-inputs-active: $all-buttons-active;
|
|
||||||
$all-button-inputs-focus: $all-buttons-focus;
|
|
||||||
$all-button-inputs-hover: $all-buttons-hover;
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Provides an easy way to include a clearfix for containing floats.
|
|
||||||
///
|
|
||||||
/// @link http://cssmojo.com/latest_new_clearfix_so_far/
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// .element {
|
|
||||||
/// @include clearfix;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// .element::after {
|
|
||||||
/// clear: both;
|
|
||||||
/// content: "";
|
|
||||||
/// display: table;
|
|
||||||
/// }
|
|
||||||
|
|
||||||
@mixin clearfix {
|
|
||||||
&::after {
|
|
||||||
clear: both;
|
|
||||||
content: "";
|
|
||||||
display: table;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Truncates text and adds an ellipsis to represent overflow.
|
|
||||||
///
|
|
||||||
/// @param {Number} $width [100%]
|
|
||||||
/// Max-width for the string to respect before being truncated
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// .element {
|
|
||||||
/// @include ellipsis;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// .element {
|
|
||||||
/// display: inline-block;
|
|
||||||
/// max-width: 100%;
|
|
||||||
/// overflow: hidden;
|
|
||||||
/// text-overflow: ellipsis;
|
|
||||||
/// white-space: nowrap;
|
|
||||||
/// word-wrap: normal;
|
|
||||||
/// }
|
|
||||||
|
|
||||||
@mixin ellipsis($width: 100%) {
|
|
||||||
display: inline-block;
|
|
||||||
max-width: $width;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
word-wrap: normal;
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Georgia font stack.
|
|
||||||
///
|
|
||||||
/// @type List
|
|
||||||
|
|
||||||
$georgia: "Georgia", "Cambria", "Times New Roman", "Times", serif;
|
|
||||||
|
|
||||||
/// Helvetica font stack.
|
|
||||||
///
|
|
||||||
/// @type List
|
|
||||||
|
|
||||||
$helvetica: "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif;
|
|
||||||
|
|
||||||
/// Lucida Grande font stack.
|
|
||||||
///
|
|
||||||
/// @type List
|
|
||||||
|
|
||||||
$lucida-grande: "Lucida Grande", "Tahoma", "Verdana", "Arial", sans-serif;
|
|
||||||
|
|
||||||
/// Monospace font stack.
|
|
||||||
///
|
|
||||||
/// @type List
|
|
||||||
|
|
||||||
$monospace: "Bitstream Vera Sans Mono", "Consolas", "Courier", monospace;
|
|
||||||
|
|
||||||
/// Verdana font stack.
|
|
||||||
///
|
|
||||||
/// @type List
|
|
||||||
|
|
||||||
$verdana: "Verdana", "Geneva", sans-serif;
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/// Hides the text in an element, commonly used to show an image. Some elements will need block-level styles applied.
|
|
||||||
///
|
|
||||||
/// @link http://zeldman.com/2012/03/01/replacing-the-9999px-hack-new-image-replacement
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// .element {
|
|
||||||
/// @include hide-text;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// .element {
|
|
||||||
/// overflow: hidden;
|
|
||||||
/// text-indent: 101%;
|
|
||||||
/// white-space: nowrap;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @todo Remove height argument in v5.0.0
|
|
||||||
|
|
||||||
@mixin hide-text($height: null) {
|
|
||||||
overflow: hidden;
|
|
||||||
text-indent: 101%;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
@if $height {
|
|
||||||
@warn "The `hide-text` mixin has changed and no longer requires a height. The height argument will no longer be accepted in v5.0.0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-26
@@ -1,26 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Provides a quick method for targeting `margin` on specific sides of a box. Use a `null` value to “skip” a side.
|
|
||||||
///
|
|
||||||
/// @param {Arglist} $vals
|
|
||||||
/// List of arguments
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// .element {
|
|
||||||
/// @include margin(null 10px 3em 20vh);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// .element {
|
|
||||||
/// margin-bottom: 3em;
|
|
||||||
/// margin-left: 20vh;
|
|
||||||
/// margin-right: 10px;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @require {mixin} directional-property
|
|
||||||
///
|
|
||||||
/// @output `margin`
|
|
||||||
|
|
||||||
@mixin margin($vals...) {
|
|
||||||
@include directional-property(margin, false, $vals...);
|
|
||||||
}
|
|
||||||
-26
@@ -1,26 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
/// Provides a quick method for targeting `padding` on specific sides of a box. Use a `null` value to “skip” a side.
|
|
||||||
///
|
|
||||||
/// @param {Arglist} $vals
|
|
||||||
/// List of arguments
|
|
||||||
///
|
|
||||||
/// @example scss - Usage
|
|
||||||
/// .element {
|
|
||||||
/// @include padding(12vh null 10px 5%);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @example css - CSS Output
|
|
||||||
/// .element {
|
|
||||||
/// padding-bottom: 10px;
|
|
||||||
/// padding-left: 5%;
|
|
||||||
/// padding-top: 12vh;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @require {mixin} directional-property
|
|
||||||
///
|
|
||||||
/// @output `padding`
|
|
||||||
|
|
||||||
@mixin padding($vals...) {
|
|
||||||
@include directional-property(padding, false, $vals...);
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user