Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab00467914 | ||
|
|
97044c2a17 | ||
|
|
8eb01a725b | ||
|
|
b074eb4f2c | ||
|
|
9dd5a1f082 | ||
|
|
e7c26b3e94 | ||
|
|
b6a0e796d8 | ||
|
|
29f726c073 | ||
|
|
0acf0bdd72 | ||
|
|
03179a0ff0 | ||
|
|
2560eae519 | ||
|
|
9113756091 | ||
|
|
f87f638f03 | ||
|
|
16f81cd411 | ||
|
|
e62c4ece90 | ||
|
|
b1baffa3d5 | ||
|
|
1d891dd313 | ||
|
|
f7edbf19b0 | ||
|
|
bbb56541f8 | ||
|
|
1d52cd551a | ||
|
|
def04042a7 | ||
|
|
46320ef4b9 | ||
|
|
5aaef1a972 | ||
|
|
f8a1d9dbf8 | ||
|
|
f8d848f383 | ||
|
|
0f7fb9430c | ||
|
|
78c2f9ee52 | ||
|
|
1a33084041 | ||
|
|
c9b03ebca1 | ||
|
|
b31f3b9335 | ||
|
|
b0d3c55bbb | ||
|
|
c2593c2207 | ||
|
|
521a00ce47 | ||
|
|
ca93a3b90d |
@@ -1,3 +1,4 @@
|
||||
html/
|
||||
build/
|
||||
firmware/
|
||||
espfs/mkespfsimage/*.o
|
||||
@@ -14,3 +15,6 @@ eagle.app.sym
|
||||
.idea/
|
||||
CMakeLists.txt
|
||||
cmake-build-debug/
|
||||
.sass-cache
|
||||
|
||||
*.map
|
||||
|
||||
@@ -65,7 +65,7 @@ LIBS += esphttpd
|
||||
# compiler flags using during compilation of source files
|
||||
CFLAGS = -Os -ggdb -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
|
||||
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \
|
||||
-Wno-address -Wno-unused
|
||||
-Wno-address -Wno-unused -DHTTPD_MAX_BACKLOG_SIZE=8192
|
||||
|
||||
# linker flags used to generate the main object file
|
||||
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static
|
||||
|
||||
@@ -13,67 +13,101 @@ Those forks include improvements not yet available upstream.
|
||||
This project aims to be a wireless terminal emulator that'll work with the likes of
|
||||
Arduino, AVR, PIC, STM8, STM32, mbed etc, anything with UART, even your USB-serial dongle will work.
|
||||
|
||||
Connect it to the master device via UART and use the terminal (on your PC or phone) for debug logging,
|
||||
Connect it to the master device via UART and use the terminal on the built-in web page for debug logging,
|
||||
remote control etc. It works like a simple LCD screen, in a way.
|
||||
|
||||
It lets you make simple UI (manipulating the screen with ANSI sequences) and receive input from buttons on
|
||||
the webpage (and keyboard on PC). Touch input is a possibility but not currently implemented.
|
||||
the webpage (and keyboard on PC). Touch input is planned as well.
|
||||
|
||||
The screen size should be adjustable up to 25x80 (via a special control sequence) and uses 16 standard colors.
|
||||
The screen size is adjustable up to 25x80 (via a special control sequence) and uses 16 standard colors
|
||||
(8 dark and 8 bright).
|
||||
|
||||
## Project status
|
||||
|
||||
*Still far from finished and also there's like zero documentation, but you can give it a spin if you wish.*
|
||||
*Almost finished, still possibly buggy, but it looks promising. Most of the features are there now.*
|
||||
|
||||
- Presently we have a working **1-way terminal** (UART->ESP->Browser) with real-time update via websocket.
|
||||
The terminal should support multiple sockets at once (not tested).
|
||||
- We have a working **2-way terminal** (UART->ESP->Browser and vice versa) with real-time update via websocket.
|
||||
|
||||
- All ANSi sequences that make sense, as well as control codes like Backspace and CR / LF are implemented.
|
||||
Set colors with your usual `\e[31;1m` etc (see Wikipedia). `\e` is the hex code 0x18 or dec 27, or ESC.
|
||||
This may be hard to type on a desktop terminal emulator, if you're trying it with a USB-serial dongle.
|
||||
It'll be easy with the microcontroller, of course.
|
||||
This means that what you type in the browser is sent to UART0 and what's received on UART0 is processed by the
|
||||
ANSI parser and applied to the internal screen buffer. You'll also immediately see the changes in your browser.
|
||||
There's a filter in the way that discards garbage characters (like unicode and most ASCII outside 32-126).
|
||||
|
||||
For a quick test, try connecting the UART0 Rx and Tx with a piece of wire to make a loopback interface.
|
||||
*NOTE: Use the bare module, not something like LoLin or NodeMCU with a FTDI, it'll interfere*.
|
||||
You should then directly see what you type & can even try some ANSI sequences, right from the browser.
|
||||
|
||||
- All ANSI sequences that make sense, as well as control codes like Backspace and CR / LF are implemented.
|
||||
Set colors with your usual `\e[31;1m` etc (see Wikipedia). `\e` is the ASCII code 27 (ESC).
|
||||
|
||||
Arrow keys generate ANSI sequences, ESC sends literal ASCII code 27 etc. Almost everything can be input
|
||||
straight from the browser.
|
||||
|
||||
- To resize the screen, send `\e]W<rows>;<cols>\a` (it's an OSC code, terminated by ST).
|
||||
|
||||
- The buttons or other input from the browser don't work yet.
|
||||
- Buttons pressed in the browser UI send ASCII codes 1..5. Mouse clicks are sent as `\e[<row>;<col>M`.
|
||||
|
||||
- There is also currently no way to set up the WiFi, so it'll use whatever you configured the ESP to
|
||||
in your previous project. This'll be addressed later.
|
||||
- There's a built-in WiFi config page and a Help page with a list of all supported ANSI sequences etc.
|
||||
|
||||
## Setting it all up
|
||||
## Development
|
||||
|
||||
### Installation for development
|
||||
|
||||
- Clone this project with `--recursive`, or afterwards run `git submodule init` and `git submodule update`.
|
||||
|
||||
- Install [esp-open-sdk](https://github.com/pfalcon/esp-open-sdk/) and build it with
|
||||
`make toolchain esptool libhal STANDALONE=n`. Make sure the `xtensa-lx106-elf/bin` folder is on $PATH.
|
||||
- Install [esptool](https://github.com/espressif/esptool) (it's in Arch community repo and on AUR, too)
|
||||
`make toolchain esptool libhal STANDALONE=n`.
|
||||
|
||||
Make sure the `xtensa-lx106-elf/bin` folder is on $PATH.
|
||||
|
||||
- Install [esptool](https://github.com/espressif/esptool) (it's in the Arch community repo and on AUR, too)
|
||||
|
||||
- Set up udev rules so you have access to ttyUSB0 without root, eg:
|
||||
|
||||
```
|
||||
KERNEL=="tty[A-Z]*[0-9]*", GROUP="uucp", MODE="0666"
|
||||
```
|
||||
- Clone this project with `--recursive`, or afterwards run `git submodule init` and `git submodule update`.
|
||||
|
||||
## Development
|
||||
- Install Ragel if you wish to make modifications to the parser.
|
||||
If not, comment out it's call in `build_parser.sh`. The `.rl` file is the actual source, the `.c` is generated.
|
||||
|
||||
The web resources are in `html_orig`. To prepare for a build, run `compress_html.sh`.
|
||||
This should pack them and put in `html`.
|
||||
- Install Ruby and then the `sass` package with `gem install sass` (or try some other implementation, such as
|
||||
`sassc`)
|
||||
|
||||
If you're missing the compression tools, you can simply copy them there manually uncompressed and hope for the best.
|
||||
- Get the IoT SDK from one of:
|
||||
|
||||
serial comm is handled in `serial.c`, sockets etc in `user_main.c`.
|
||||
```
|
||||
ESP8266_NONOS_SDK_V2.0.0_16_08_10.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1690"
|
||||
ESP8266_NONOS_SDK_V2.0.0_16_07_19.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1613"
|
||||
ESP8266_NONOS_SDK_V1.5.4_16_05_20.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1469"
|
||||
ESP8266_NONOS_SDK_V1.5.3_16_04_18.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1361"
|
||||
ESP8266_NONOS_SDK_V1.5.2_16_01_29.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1079"
|
||||
```
|
||||
|
||||
Get the IoT SDK from one of:
|
||||
It's tested with 1.5.2, 2.0.0 won't work without adjusting the build scripts. Any 1.5.x could be fine.
|
||||
|
||||
```
|
||||
ESP8266_NONOS_SDK_V2.0.0_16_08_10.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1690"
|
||||
ESP8266_NONOS_SDK_V2.0.0_16_07_19.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1613"
|
||||
ESP8266_NONOS_SDK_V1.5.4_16_05_20.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1469"
|
||||
ESP8266_NONOS_SDK_V1.5.3_16_04_18.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1361"
|
||||
ESP8266_NONOS_SDK_V1.5.2_16_01_29.zip:
|
||||
wget --content-disposition "http://bbs.espressif.com/download/file.php?id=1079"
|
||||
```
|
||||
The `esp-open-sdk` Makefile could also download this for you with the right flags.
|
||||
|
||||
It's tested with 1.5.2, 2.0.0 won't work without adjusting the build scripts. Any 1.5.x could be fine.
|
||||
- Make sure your `esphttpdconfig.mk` is set up properly - link to the SDK etc.
|
||||
|
||||
To flash, just run `make flash`. First make sure your `esphttpdconfig.mk` is set up properly - link to sdk etc.
|
||||
### Web resources
|
||||
|
||||
The web resources are in `html_orig`. To prepare for a build, run `build_web.sh`, which packs them and
|
||||
copies over to `html`. The compression and minification is handled by scripts in libesphttpd, specifically
|
||||
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"
|
||||
Makefile option, then you can flash just the html portion with `make htmlflash`. I haven't tried this.
|
||||
|
||||
### Flashing
|
||||
|
||||
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
|
||||
build scripts manually, too.
|
||||
|
||||
To flash, just run `make flash`.
|
||||
|
||||
+26
-4
@@ -2,7 +2,29 @@
|
||||
|
||||
echo "-- Preparing WWW files --"
|
||||
|
||||
mkdir -p html
|
||||
yuicompressor html_orig/style.css > html/style.css
|
||||
yuicompressor html_orig/script.js > html/script.js
|
||||
minify --type=html html_orig/term.html -o html/term.tpl
|
||||
[[ -e html ]] && rm -r html
|
||||
mkdir -p html/img
|
||||
mkdir -p html/js
|
||||
mkdir -p html/css
|
||||
|
||||
# Join scripts
|
||||
DD=html_orig/jssrc
|
||||
cat $DD/chibi.js \
|
||||
$DD/utils.js \
|
||||
$DD/modal.js \
|
||||
$DD/appcommon.js \
|
||||
$DD/term.js \
|
||||
$DD/wifi.js > html/js/app.js
|
||||
|
||||
sass --sourcemap=none html_orig/sass/app.scss html_orig/css/app.css
|
||||
|
||||
# No need to compress CSS and JS now, we run YUI on it later
|
||||
cp html_orig/css/app.css html/css/app.css
|
||||
cp html_orig/term.html html/term.tpl
|
||||
cp html_orig/wifi.html html/wifi.tpl
|
||||
cp html_orig/about.html html/about.tpl
|
||||
cp html_orig/help.html html/help.tpl
|
||||
cp html_orig/wifi_conn.html html/wifi_conn.tpl
|
||||
cp html_orig/img/loader.gif html/img/loader.gif
|
||||
cp html_orig/img/cvut.svg html/img/cvut.svg
|
||||
cp html_orig/favicon.ico html/favicon.ico
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
var $=function(d,c){d=d.match(/^(\W)?(.*)/);return(c||document)["getElement"+(d[1]?d[1]=="#"?"ById":"sByClassName":"sByTagName")](d[2])};var m=function(e,d,f){d=document;f=d.createElement("p");f.innerHTML=e;e=d.createDocumentFragment();while(d=f.firstChild){e.appendChild(d)}return e};(function(){function a(r){return document.createElement(r)}var b=26,k=10;var l={a:false,x:0,y:0,suppress:false,hidden:false};var o=[];var g=["#111213","#CC0000","#4E9A06","#C4A000","#3465A4","#75507B","#06989A","#D3D7CF","#555753","#EF2929","#8AE234","#FCE94F","#729FCF","#AD7FA8","#34E2E2","#EEEEEC"];function p(){o.forEach(function(r,s){r.t=" ";r.fg=7;r.bg=0;d(r)})}function c(s,r){return o[s*b+r]}function i(){return c(l.y,l.x)}function q(r){l.hidden=!r;l.a&=r;d(i(),l.a)}function f(s,r){l.suppress=true;d(i(),false);l.x=r;l.y=s;l.suppress=false;d(i(),l.a)}function d(s,r){var v=s.e,t,u;t=r?s.bg:s.fg;u=r?s.fg:s.bg;v.innerText=(s.t+" ")[0];v.style.color=e(t);v.style.backgroundColor=e(u);v.style.fontWeight=t>7?"bold":"normal"}function h(){o.forEach(function(s,t){var r=l.a&&(t==l.y*b+l.x);d(s,r)})}function j(v){l.x=v.x;l.y=v.y;var w=0,C=0,y=v.screen;var r=7,x=0;while(w<y.length&&C<b*k){var A=o[C++];var u=y[w];if(u!=","){r=A.fg=parseInt(y[w++],16);x=A.bg=parseInt(y[w++],16)}else{w++;A.fg=r;A.bg=x}var B=A.t=y[w++];var s=0;switch(y[w]){case"r":s=1;break;case"s":s=2;break;case"t":s=3;break;case"u":s=4;break;default:s=0}if(s>0){var z=parseInt(y.substr(w+1,s));w=w+s+1;for(;z>0&&C<b*k;z--){A=o[C++];A.fg=r;A.bg=x;A.t=B}}}h()}function e(r){r=parseInt(r);if(r<0||r>15){r=0}return g[r]}function n(v){var u,r,t=$("#screen");for(var s=0;s<b*k;s++){u=a("span");if((s>0)&&(s%b==0)){t.appendChild(a("br"))}t.appendChild(u);r={t:" ",fg:7,bg:0,e:u};o.push(r);d(r)}setInterval(function(){l.a=!l.a;if(l.hidden){l.a=false}if(!l.suppress){d(i(),l.a)}},500);j(v)}window.Term={init:n,load:j,setCursor:f,enableCursor:q,clear:p}})();(function(){var g="ws://"+window.location.host+"/ws/update.cgi";var d;function c(i){console.log("CONNECTED")}function b(i){console.error("SOCKET CLOSED")}function f(i){try{console.log("RX: ",i.data);Term.load(JSON.parse(i.data))}catch(j){console.error(j)}}function e(i){console.error(i.data)}function a(i){if(typeof i!="string"){i=JSON.stringify(i)}d.send(i)}function h(){d=new WebSocket(g);d.onopen=c;d.onclose=b;d.onmessage=f;d.onerror=e;console.log("Opening socket.")}window.Conn={ws:null,init:h,send:a}})();function init(a){Term.init(a);Conn.init()};
|
||||
@@ -1 +0,0 @@
|
||||
html,body{background:#48505f;color:#eee;font-family:monospace;font-size:16pt;text-align:center}header{font-weight:bold;font-size:14pt;padding:6px;display:block}#screen{display:block;white-space:nowrap;background:#111213;border-radius:3px;padding:6px;box-shadow:inset 0 0 5px black;display:inline-block}#screen span{white-space:pre}#buttons{margin-top:10px}button{margin:0 2px;padding:10px 0;width:22%;max-width:80px;cursor:pointer}
|
||||
@@ -1 +0,0 @@
|
||||
<!doctype html><meta charset=utf-8><title>ESP8266 Remote Terminal</title><meta name=viewport content="width=device-width,shrink-to-fit=no,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link rel=stylesheet href=style.css><script src=script.js></script><header>ESP8266 Remote Terminal</header><div id=screen></div><div id=buttons><button>1</button><button>2</button><button>3</button><button>4</button></div><script>init(%screenData%)</script>
|
||||
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>About - ESP8266 Remote Terminal</title>
|
||||
<meta name="viewport" content="width=device-width,shrink-to-fit=no,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
|
||||
|
||||
<link rel="stylesheet" href="/css/app.css">
|
||||
<script src="/js/app.js"></script>
|
||||
</head>
|
||||
<body class="page-about">
|
||||
|
||||
<h1 onclick="location.href='/'">About</h1>
|
||||
|
||||
<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, 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>Firmware</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Firmware</th>
|
||||
<td>v%vers_fw%, build <i>%date%</i> at <i>%time%</i></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.
|
||||
</p>
|
||||
<p>
|
||||
Firmware updates can be downloaded from the <a href="%githubrepo%/releases">releases page</a>.
|
||||
Flash the images using <a href="https://github.com/espressif/esptool">esptool</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="Box">
|
||||
<h2>Contributing</h2>
|
||||
<p>
|
||||
Submit your improvements and ideas to the project on <a href="%githubrepo%">GitHub</a>.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="Box">
|
||||
<h2>Acknowledgements</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>
|
||||
|
||||
<nav id="botnav">
|
||||
<a href="/">Terminal</a><!--
|
||||
--><a href="/help">Help</a><!--
|
||||
--><a href="/wifi">WiFi config</a>
|
||||
</nav>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,868 @@
|
||||
/* 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.
|
||||
*/
|
||||
figure,
|
||||
nav
|
||||
{
|
||||
display: block; }
|
||||
|
||||
/**
|
||||
* 1. Correct `inline-block` display not defined in IE 8/9.
|
||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
canvas,
|
||||
progress
|
||||
{
|
||||
display: inline-block;
|
||||
/* 1 */
|
||||
vertical-align: baseline;
|
||||
/* 2 */ }
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
/**
|
||||
* 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]
|
||||
{
|
||||
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.
|
||||
*/
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
b
|
||||
{
|
||||
font-weight: bold; }
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari and Chrome.
|
||||
*/
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* 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,
|
||||
pre
|
||||
{
|
||||
font-family: 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,
|
||||
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,
|
||||
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`.
|
||||
*/
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
|
||||
*/
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/* Tables
|
||||
========================================================================== */
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0; }
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0; }
|
||||
|
||||
html {
|
||||
box-sizing: border-box; }
|
||||
|
||||
*, *::after, *::before {
|
||||
box-sizing: inherit; }
|
||||
|
||||
.hidden {
|
||||
display: none !important; }
|
||||
|
||||
[onclick] {
|
||||
cursor: pointer; }
|
||||
|
||||
.Modal {
|
||||
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(0, 0, 0, 0.65);
|
||||
opacity: 0; }
|
||||
.Modal.visible {
|
||||
opacity: 1; }
|
||||
.Modal.hidden {
|
||||
display: none; }
|
||||
|
||||
.Dialog {
|
||||
margin: 0.61805rem;
|
||||
padding: 1rem;
|
||||
overflow: hidden;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
flex: 0 1 30rem;
|
||||
background: #1c1c1e;
|
||||
border-left: 6px solid #2972ba;
|
||||
border-right: 6px solid #2972ba;
|
||||
box-shadow: 0 0 2px 0 #434349, 0 0 6px 0 black;
|
||||
border-radius: 6px; }
|
||||
.Dialog h1, .Dialog h2 {
|
||||
margin-top: 0; }
|
||||
.Dialog p:last-child {
|
||||
margin-bottom: 0; }
|
||||
|
||||
/*
|
||||
// "toast"
|
||||
.NotifyMsg {
|
||||
position: fixed;
|
||||
bottom: 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: #37a349;
|
||||
&.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% - 1rem);
|
||||
}
|
||||
|
||||
transition: opacity .5s;
|
||||
opacity: 0;
|
||||
&.visible { opacity: 1 }
|
||||
&.hidden { display: none }
|
||||
}
|
||||
*/
|
||||
html {
|
||||
font-family: Arial, sans-serif;
|
||||
color: #D0D0D0;
|
||||
background: #131315; }
|
||||
|
||||
html, body {
|
||||
border: 0 none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-decoration: none;
|
||||
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; }
|
||||
|
||||
.Box {
|
||||
display: block;
|
||||
max-width: 900px;
|
||||
margin-top: 1rem;
|
||||
padding: 0.61805rem 1rem;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(255, 255, 255, 0.07); }
|
||||
@media screen and (max-width: 544px) {
|
||||
.Box {
|
||||
margin-top: 0.61805rem;
|
||||
padding: 0.23608rem 0.38198rem; } }
|
||||
.Box p:first-child {
|
||||
margin-top: 0; }
|
||||
|
||||
body {
|
||||
position: relative;
|
||||
padding: 1rem;
|
||||
overflow-y: auto; }
|
||||
@media screen and (max-width: 544px) {
|
||||
body {
|
||||
padding: 0.61805rem; } }
|
||||
body > * {
|
||||
margin-left: auto;
|
||||
margin-right: auto; }
|
||||
|
||||
h1, h2 {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none; }
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 2.02729em;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem; }
|
||||
@media screen and (max-width: 544px) {
|
||||
h1 {
|
||||
font-size: 1.42383em;
|
||||
margin-bottom: 0.61805rem; } }
|
||||
@media screen and (min-width: 545px) and (max-width: 1000px) {
|
||||
h1 {
|
||||
font-size: 1.80203em; } }
|
||||
|
||||
h2 {
|
||||
font-size: 1.26563em;
|
||||
margin-bottom: 0.61805rem; }
|
||||
|
||||
td, th {
|
||||
padding: 0.38198rem;
|
||||
white-space: nowrap; }
|
||||
@media screen and (max-width: 544px) {
|
||||
td, th {
|
||||
padding: 0.23608rem; } }
|
||||
|
||||
tbody th {
|
||||
text-align: right;
|
||||
width: 130px;
|
||||
color: white; }
|
||||
@media screen and (max-width: 544px) {
|
||||
tbody th {
|
||||
width: auto; } }
|
||||
|
||||
tbody td input[type="text"], tbody td input[type="number"] {
|
||||
width: 10em; }
|
||||
@media screen and (max-width: 544px) {
|
||||
tbody td input[type="text"], tbody td input[type="number"] {
|
||||
width: 8em; } }
|
||||
|
||||
#loader {
|
||||
position: absolute;
|
||||
right: 1.618rem;
|
||||
top: 1.618rem;
|
||||
transition: opacity .2s;
|
||||
opacity: 0; }
|
||||
@media screen and (max-width: 544px) {
|
||||
#loader {
|
||||
top: 1rem;
|
||||
right: 1rem; } }
|
||||
#loader.show {
|
||||
opacity: 1; }
|
||||
|
||||
ul > * {
|
||||
padding-top: .1em;
|
||||
padding-bottom: .1em; }
|
||||
|
||||
#botnav {
|
||||
padding-top: 1.5em;
|
||||
text-align: center; }
|
||||
#botnav a {
|
||||
padding: 0 0.38198rem;
|
||||
text-decoration: underline; }
|
||||
#botnav a, #botnav a:visited, #botnav a:link {
|
||||
color: #2e4d6e; }
|
||||
#botnav a:hover {
|
||||
color: #5abfff; }
|
||||
|
||||
button, input[type=submit], .button {
|
||||
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;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
text-shadow: 1.5px 1.5px 2px rgba(0, 0, 0, 0.6);
|
||||
background-color: #3983cd;
|
||||
box-shadow: 0 3px 0 #265f98;
|
||||
text-decoration: none !important; }
|
||||
button:active, input[type=submit]:active, .button:active {
|
||||
position: relative;
|
||||
top: 2px; }
|
||||
button.narrow, input[type=submit].narrow, .button.narrow {
|
||||
min-width: initial; }
|
||||
button, button:link, button:visited, input[type=submit], input[type=submit]:link, input[type=submit]:visited, .button, .button:link, .button:visited {
|
||||
color: #FEFEFE; }
|
||||
button:hover, button:active, button.active, button.selected, input[type=submit]:hover, input[type=submit]:active, input[type=submit].active, input[type=submit].selected, .button:hover, .button:active, .button.active, .button.selected {
|
||||
background-color: #2076C6;
|
||||
color: #FEFEFE; }
|
||||
button:hover, button.selected, button.active, input[type=submit]:hover, input[type=submit].selected, input[type=submit].active, .button:hover, .button.selected, .button.active {
|
||||
box-shadow: 0 3px 0 #154c80; }
|
||||
button:active, input[type=submit]:active, .button:active {
|
||||
box-shadow: 0 1px 0 #154c80; }
|
||||
|
||||
button, input[type=submit], .button {
|
||||
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;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
text-shadow: 1.5px 1.5px 2px rgba(0, 0, 0, 0.6);
|
||||
background-color: #3983cd;
|
||||
box-shadow: 0 3px 0 #265f98;
|
||||
text-decoration: none !important; }
|
||||
button:active, input[type=submit]:active, .button:active {
|
||||
position: relative;
|
||||
top: 2px; }
|
||||
button.narrow, input[type=submit].narrow, .button.narrow {
|
||||
min-width: initial; }
|
||||
button, button:link, button:visited, input[type=submit], input[type=submit]:link, input[type=submit]:visited, .button, .button:link, .button:visited {
|
||||
color: #FEFEFE; }
|
||||
button:hover, button:active, button.active, button.selected, input[type=submit]:hover, input[type=submit]:active, input[type=submit].active, input[type=submit].selected, .button:hover, .button:active, .button.active, .button.selected {
|
||||
background-color: #2076C6;
|
||||
color: #FEFEFE; }
|
||||
button:hover, button.selected, button.active, input[type=submit]:hover, input[type=submit].selected, input[type=submit].active, .button:hover, .button.selected, .button.active {
|
||||
box-shadow: 0 3px 0 #154c80; }
|
||||
button:active, input[type=submit]:active, .button:active {
|
||||
box-shadow: 0 1px 0 #154c80; }
|
||||
|
||||
input[type="number"], input[type="password"], input[type="text"], textarea, select {
|
||||
border: 0 none;
|
||||
border-bottom: 2px solid #214e7a;
|
||||
background-color: #303030;
|
||||
color: white;
|
||||
padding: 6px;
|
||||
line-height: 1em;
|
||||
outline: 0 none !important;
|
||||
-moz-outline: 0 none !important;
|
||||
font-weight: normal; }
|
||||
input[type="number"]:focus, input[type="number"]:hover, input[type="password"]:focus, input[type="password"]:hover, input[type="text"]:focus, input[type="text"]:hover, textarea:focus, textarea:hover, select:focus, select:hover {
|
||||
border-bottom-color: #2972ba; }
|
||||
|
||||
#psk-modal form > *, #wificonfbox form > * {
|
||||
margin-right: 0.38198rem; }
|
||||
#psk-modal form > *:last-child, #wificonfbox form > *:last-child {
|
||||
margin-right: 0; }
|
||||
|
||||
#ap-list {
|
||||
column-count: 3;
|
||||
column-gap: 0;
|
||||
margin: 0 -0.23608rem; }
|
||||
@media screen and (min-width: 545px) and (max-width: 1000px) {
|
||||
#ap-list {
|
||||
column-count: 2; } }
|
||||
@media screen and (max-width: 544px) {
|
||||
#ap-list {
|
||||
column-count: 1; } }
|
||||
|
||||
#ap-loader, #ap-noscan {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 5px;
|
||||
padding: 0.38198rem;
|
||||
margin-bottom: 0.38198rem; }
|
||||
|
||||
#ap-noscan {
|
||||
font-weight: bold; }
|
||||
|
||||
#ap-box {
|
||||
padding-bottom: 0.38198rem; }
|
||||
|
||||
#psk-modal form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0.38198rem; }
|
||||
#psk-modal form input[type=password] {
|
||||
min-width: 5rem; }
|
||||
|
||||
.AP {
|
||||
break-inside: avoid-column;
|
||||
max-width: 500px;
|
||||
padding: 0.23608rem; }
|
||||
.AP.selected .inner {
|
||||
background: #42a6f9 !important;
|
||||
cursor: default;
|
||||
top: 0 !important; }
|
||||
.AP .inner {
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
border-radius: 3px;
|
||||
color: #222;
|
||||
background: #afafaf;
|
||||
transition: background-color 0.5s;
|
||||
display: flex; }
|
||||
.AP .inner:active {
|
||||
left: 0;
|
||||
top: 1px; }
|
||||
.AP .inner:hover {
|
||||
background: white; }
|
||||
.AP .inner > * {
|
||||
padding: 0.61805rem;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal; }
|
||||
.AP .inner .rssi {
|
||||
min-width: 2.5rem;
|
||||
flex: 0 0 15%;
|
||||
text-align: right; }
|
||||
.AP .inner .rssi:after {
|
||||
padding-left: 0.09018rem;
|
||||
content: '%';
|
||||
font-size: 0.88889em; }
|
||||
.AP .inner .essid {
|
||||
flex: 1 1 70%;
|
||||
min-width: 0;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
font-weight: bold; }
|
||||
.AP .inner .auth {
|
||||
flex: 0 0 15%; }
|
||||
|
||||
.page-term h1 {
|
||||
font-size: 1.80203em; }
|
||||
@media screen and (max-width: 544px) {
|
||||
.page-term h1 {
|
||||
font-size: 1.42383em; } }
|
||||
.page-term #screen {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
font-family: monospace;
|
||||
font-size: 16pt;
|
||||
white-space: nowrap;
|
||||
background: #111213;
|
||||
padding: 6px;
|
||||
display: inline-block;
|
||||
border: 2px solid #3983CD; }
|
||||
.page-term #screen span {
|
||||
white-space: pre;
|
||||
cursor: pointer; }
|
||||
.page-term #screen span:hover {
|
||||
outline: 1px solid rgba(255, 255, 255, 0.4); }
|
||||
@media screen and (max-width: 544px) {
|
||||
.page-term #screen span:hover {
|
||||
outline: 0 none; } }
|
||||
.page-term #buttons {
|
||||
margin-top: 10px;
|
||||
white-space: nowrap; }
|
||||
.page-term #buttons button {
|
||||
margin: 0 3px;
|
||||
padding: 10px 0;
|
||||
width: 18%;
|
||||
max-width: 65px;
|
||||
min-width: initial;
|
||||
cursor: pointer;
|
||||
font-weight: bold; }
|
||||
|
||||
#termwrap {
|
||||
text-align: center; }
|
||||
|
||||
.page-about .Box {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem; }
|
||||
.page-about .Box a {
|
||||
font-weight: bold; }
|
||||
.page-about #logo {
|
||||
float: right;
|
||||
height: 130px; }
|
||||
.page-about #logo2 {
|
||||
max-width: 100%; }
|
||||
.page-about td {
|
||||
white-space: normal; }
|
||||
|
||||
.colorprev {
|
||||
margin-top: 0.38198rem;
|
||||
margin-bottom: 0.38198rem; }
|
||||
.colorprev span {
|
||||
display: inline-block;
|
||||
width: 2em;
|
||||
padding: 0.38198rem 0;
|
||||
text-align: center; }
|
||||
|
||||
.ansiref, .ansiref td, .ansiref th {
|
||||
border: 1px solid #666; }
|
||||
.ansiref th, .ansiref td {
|
||||
white-space: normal; }
|
||||
.ansiref th {
|
||||
background-color: rgba(255, 255, 255, 0.1); }
|
||||
.ansiref td:nth-child(1) {
|
||||
font-family: monospace; }
|
||||
.ansiref.w100 {
|
||||
width: 100%; }
|
||||
.ansiref.w100 td:nth-child(1) {
|
||||
width: 9em; }
|
||||
.ansiref.w100 td:nth-child(2) {
|
||||
width: 8em; }
|
||||
|
||||
.fg0 {
|
||||
color: #111213; }
|
||||
|
||||
.bg0 {
|
||||
background-color: #111213; }
|
||||
|
||||
.fg1 {
|
||||
color: #CC0000; }
|
||||
|
||||
.bg1 {
|
||||
background-color: #CC0000; }
|
||||
|
||||
.fg2 {
|
||||
color: #4E9A06; }
|
||||
|
||||
.bg2 {
|
||||
background-color: #4E9A06; }
|
||||
|
||||
.fg3 {
|
||||
color: #C4A000; }
|
||||
|
||||
.bg3 {
|
||||
background-color: #C4A000; }
|
||||
|
||||
.fg4 {
|
||||
color: #3465A4; }
|
||||
|
||||
.bg4 {
|
||||
background-color: #3465A4; }
|
||||
|
||||
.fg5 {
|
||||
color: #75507B; }
|
||||
|
||||
.bg5 {
|
||||
background-color: #75507B; }
|
||||
|
||||
.fg6 {
|
||||
color: #06989A; }
|
||||
|
||||
.bg6 {
|
||||
background-color: #06989A; }
|
||||
|
||||
.fg7 {
|
||||
color: #D3D7CF; }
|
||||
|
||||
.bg7 {
|
||||
background-color: #D3D7CF; }
|
||||
|
||||
.fg8 {
|
||||
color: #555753; }
|
||||
|
||||
.bg8 {
|
||||
background-color: #555753; }
|
||||
|
||||
.fg9 {
|
||||
color: #EF2929; }
|
||||
|
||||
.bg9 {
|
||||
background-color: #EF2929; }
|
||||
|
||||
.fg10 {
|
||||
color: #8AE234; }
|
||||
|
||||
.bg10 {
|
||||
background-color: #8AE234; }
|
||||
|
||||
.fg11 {
|
||||
color: #FCE94F; }
|
||||
|
||||
.bg11 {
|
||||
background-color: #FCE94F; }
|
||||
|
||||
.fg12 {
|
||||
color: #729FCF; }
|
||||
|
||||
.bg12 {
|
||||
background-color: #729FCF; }
|
||||
|
||||
.fg13 {
|
||||
color: #AD7FA8; }
|
||||
|
||||
.bg13 {
|
||||
background-color: #AD7FA8; }
|
||||
|
||||
.fg14 {
|
||||
color: #34E2E2; }
|
||||
|
||||
.bg14 {
|
||||
background-color: #34E2E2; }
|
||||
|
||||
.fg15 {
|
||||
color: #EEEEEC; }
|
||||
|
||||
.bg15 {
|
||||
background-color: #EEEEEC; }
|
||||
|
||||
.fg8, .fg9, .fg10, .fg11, .fg12, .fg13, .fg14, .fg15 {
|
||||
font-weight: bold; }
|
||||
|
||||
.nb {
|
||||
font-weight: normal !important; }
|
||||
|
||||
@media screen and (min-width: 545px) {
|
||||
.mq-phone {
|
||||
display: none; } }
|
||||
@media screen and (max-width: 544px) {
|
||||
.mq-tablet-min {
|
||||
display: none; } }
|
||||
@media screen and (min-width: 1001px) {
|
||||
.mq-tablet-max {
|
||||
display: none; } }
|
||||
@media screen and (max-width: 1000px) {
|
||||
.mq-normal-min {
|
||||
display: none; } }
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 318 B |
@@ -0,0 +1,339 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Help - ESP8266 Remote Terminal</title>
|
||||
<meta name="viewport" content="width=device-width,shrink-to-fit=no,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
|
||||
|
||||
<link rel="stylesheet" href="/css/app.css">
|
||||
<script src="/js/app.js"></script>
|
||||
</head>
|
||||
<body class="page-help">
|
||||
|
||||
<h1 onclick="location.href='/'">Quick Reference</h1>
|
||||
|
||||
<div class="Box">
|
||||
<h2>Wiring</h2>
|
||||
|
||||
<ul>
|
||||
<li>Communication UART on pins <b>Rx, Tx</b> at 115200-8-1-N</li>
|
||||
<li>Debug log on pin <b>GPIO2</b> at 115200-8-1-N</li>
|
||||
<li>Use 3.3V logic, or 5V with protection resistors (470R or more)</li>
|
||||
<li>If the "LVD" LED on the ESP Term board lights up, the module doesn't get enough power. Check your connections.</li>
|
||||
<li>Connect Rx and Tx with a piece of wire to test the terminal alone, you should see what you type in the browser.
|
||||
NOTE: This won't work if your ESP8266 board has a built-in USB-serial (like NodeMCU).</li>
|
||||
<li>For best performance, use the module in the Client mode. In AP mode, check that the channel used is clear;
|
||||
interference may cause lag in the terminal.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="Box">
|
||||
<h2>Screen</h2>
|
||||
|
||||
<ul>
|
||||
<li>Most ANSI escape sequences are supported.</li>
|
||||
<li>The max screen size is 2000 characters (eg. <b>25x80</b>), default is <b>10x26</b>. Set using <code>\e]W<rows>;<cols>\a</code>.</li>
|
||||
<li>The screen will automatically scroll, can be used for log output.</li>
|
||||
<li>Display update is sent <b>after 20 ms of inactivity</b>.</li>
|
||||
<li>At most 4 clients can be connected at the same time.</li>
|
||||
<li>The browser display needs WebSockets for the real-time updating. It may not work on really old phones / browsers.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="Box">
|
||||
<h2>Color Reference</h2>
|
||||
|
||||
<p>Color is set using <code>\e[<c>m</code> or <code>\e[<c>;<c>m</code> where "<c>" are numbers from the following tables:</p>
|
||||
|
||||
<b>Foreground</b>
|
||||
|
||||
<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="bg7 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>
|
||||
|
||||
<b>Background</b>
|
||||
|
||||
<div class="colorprev">
|
||||
<span class="bg0 fg15 nb">40</span>
|
||||
<span class="bg1 fg15 nb">41</span>
|
||||
<span class="bg2 fg15 nb">42</span>
|
||||
<span class="bg3 fg0">43</span>
|
||||
<span class="bg4 fg15 nb">44</span>
|
||||
<span class="bg5 fg15 nb">45</span>
|
||||
<span class="bg6 fg15 nb">46</span>
|
||||
<span class="bg7 fg0">47</span>
|
||||
</div>
|
||||
|
||||
<div class="colorprev">
|
||||
<span class="bg8 fg15 nb">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>
|
||||
|
||||
<p>Bright foreground can also be set using the "bold" attribute 1 (eg. <code>\e[31;1m</code>). For more details, see the ANSI code reference below.</p>
|
||||
</div>
|
||||
|
||||
<div class="Box">
|
||||
<h2>User Input</h2>
|
||||
|
||||
<p>
|
||||
All the user types on their keyboard is sent as-is to the UART, including ESC, ANSI sequences for arrow keys and CR-LF for Enter.
|
||||
The input is limited to ASCII codes 32-126, backspace 8 and tab 9.
|
||||
</p>
|
||||
|
||||
<p>The buttons under the screen send ASCII codes 1, 2, 3, 4, 5.</p>
|
||||
|
||||
<p>
|
||||
<b>Mouse input</b> (click/tap) is sent as <code>\e[<y>;<x>M</code>. You can use this for on-screen buttons, menu navigation etc.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="Box">
|
||||
<h2>Supported ANSI Escape Sequences</h2>
|
||||
|
||||
<p>Sequences are started by ASCII code 27 (ESC, <code>\e</code>, <code>\x1b</code>, <code>\033</code>)</p>
|
||||
|
||||
<p>Instead of <code>\a</code> (BELL, ASCII 7) in the commands, you can use `\e\` (ESC + backslash). It's the Text Separator code.</p>
|
||||
|
||||
<h3>Text Attributes</h3>
|
||||
|
||||
<p>
|
||||
All text attributes are set using <code>\e[...m</code> where the dots are numbers separated by semicolons.
|
||||
You can combine up to 3 attributes in a single command.
|
||||
</p>
|
||||
|
||||
<table class="ansiref">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Attribute</th>
|
||||
<th>Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>Reset text attributes to default</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>7</td>
|
||||
<td>Inverse (fg/bg swap when printing)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>27</td>
|
||||
<td>Inverse OFF</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>30-37, 90-97</td>
|
||||
<td>Foreground color, normal and bright</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>40-47, 100-107</td>
|
||||
<td>Background color, normal and bright</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>Cursor</h3>
|
||||
|
||||
<p>Movement commands scroll the screen if needed. The coordinates are 1-based, origin top left.</p>
|
||||
|
||||
<table class="ansiref w100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Code</th>
|
||||
<th>Params</th>
|
||||
<th>Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>\e[<n>A</td>
|
||||
<td>[count]</td>
|
||||
<td>Move cursor up</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<n>B</td>
|
||||
<td>[count]</td>
|
||||
<td>Move cursor down</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<n>C</td>
|
||||
<td>[count]</td>
|
||||
<td>Move cursor forward (right)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<n>D</td>
|
||||
<td>[count]</td>
|
||||
<td>Move cursor backward (left)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<n>E</td>
|
||||
<td>[count]</td>
|
||||
<td>Go N line down, start of line</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<n>F</td>
|
||||
<td>[count]</td>
|
||||
<td>Go N lines up, start of line</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<n>G</td>
|
||||
<td>column</td>
|
||||
<td>Go to column</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<y>;<x>G</td>
|
||||
<td>[row=1];[col=1]</td>
|
||||
<td>Go to row and column</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[6n</td>
|
||||
<td>--</td>
|
||||
<td>Query cursor position. Position is sent back as <code>\e[?;?R</code> with row;column.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[s</td>
|
||||
<td>--</td>
|
||||
<td>Store position</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[u</td>
|
||||
<td>--</td>
|
||||
<td>Restore position</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e7</td>
|
||||
<td>--</td>
|
||||
<td>Store position & attributes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e8</td>
|
||||
<td>--</td>
|
||||
<td>Restore position & attributes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[?25l</td>
|
||||
<td>--</td>
|
||||
<td>Hide cursor</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[?25h</td>
|
||||
<td>--</td>
|
||||
<td>Show cursor</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[?7l</td>
|
||||
<td>--</td>
|
||||
<td>Disable cursor auto-wrap & auto-scroll at end of screen</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[?7h</td>
|
||||
<td>--</td>
|
||||
<td>Enable cursor auto-wrap & auto-scroll at end of screen</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>Screen</h3>
|
||||
|
||||
<table class="ansiref w100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Code</th>
|
||||
<th>Params</th>
|
||||
<th>Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>\e[<m>J</td>
|
||||
<td>[mode=0]</td>
|
||||
<td>Clear screen. Mode: 0 - from cursor, 1 - to cursor, 2 - all</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<m>K</td>
|
||||
<td>[mode=0]</td>
|
||||
<td>Erase line. Mode: 0 - from cursor, 1 - to cursor, 2 - all</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<n>S</td>
|
||||
<td>[lines]</td>
|
||||
<td>Scroll screen content up, add empty line at the bottom</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[<n>T</td>
|
||||
<td>[lines]</td>
|
||||
<td>Scroll screen content down, add empty line at the top</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e]W<r>;<c>\a</td>
|
||||
<td>rows;cols</td>
|
||||
<td>Set screen size, maximum 25x80 (resp. total 2000 characters). This also clears the screen.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>System Commands</h3>
|
||||
|
||||
<table class="ansiref w100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Code</th>
|
||||
<th>Params</th>
|
||||
<th>Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>\ec</td>
|
||||
<td>--</td>
|
||||
<td>
|
||||
"Device Reset" - clear screen, reset attributes, show cursor & move it to 1,1.
|
||||
The screen size and WiFi settings stay unchanged.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e]FR\a</td>
|
||||
<td>--</td>
|
||||
<td>"Factory Reset", emergency code when you mess up the WiFi, restores SSID to unique default, clears stored credentials & enters Client+AP mode.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\e[5n</td>
|
||||
<td>--</td>
|
||||
<td>Query device status, replies with <code>\e[0n</code> "device is OK". Can be used to check if the UART works.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<nav id="botnav">
|
||||
<a href="/">Terminal</a><!--
|
||||
--><a href="/wifi">WiFi config</a><!--
|
||||
--><a href="/about">About</a>
|
||||
</nav>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Executable
+5
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.8 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
+1369
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
/** Global generic init */
|
||||
$.ready(function () {
|
||||
// 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 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();
|
||||
});
|
||||
|
||||
Modal.init();
|
||||
});
|
||||
|
||||
$._loader = function(vis) {
|
||||
if(vis)
|
||||
$('#loader').addClass('show');
|
||||
else
|
||||
$('#loader').removeClass('show');
|
||||
};
|
||||
Executable
+702
@@ -0,0 +1,702 @@
|
||||
/*!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) {
|
||||
classHelper(classes, 'toggle', 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;
|
||||
}());
|
||||
@@ -0,0 +1,41 @@
|
||||
/** Module for toggling a modal overlay */
|
||||
(function () {
|
||||
var modal = {};
|
||||
|
||||
modal.show = function (sel) {
|
||||
var $m = $(sel);
|
||||
$m.removeClass('hidden visible');
|
||||
setTimeout(function () {
|
||||
$m.addClass('visible');
|
||||
}, 1);
|
||||
};
|
||||
|
||||
modal.hide = function (sel) {
|
||||
var $m = $(sel);
|
||||
$m.removeClass('visible');
|
||||
setTimeout(function () {
|
||||
$m.addClass('hidden');
|
||||
}, 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;
|
||||
})();
|
||||
@@ -0,0 +1,303 @@
|
||||
(function() {
|
||||
/**
|
||||
* Terminal module
|
||||
*/
|
||||
var Term = (function () {
|
||||
var W, H;
|
||||
var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false};
|
||||
var screen = [];
|
||||
var blinkIval;
|
||||
|
||||
/*
|
||||
/!** Clear screen *!/
|
||||
function cls() {
|
||||
screen.forEach(function(cell, i) {
|
||||
cell.t = ' ';
|
||||
cell.fg = 7;
|
||||
cell.bg = 0;
|
||||
blit(cell);
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
/** Set text and color at XY */
|
||||
function cellAt(y, x) {
|
||||
return screen[y*W+x];
|
||||
}
|
||||
|
||||
/** Get cell under cursor */
|
||||
function cursorCell() {
|
||||
return cellAt(cursor.y, cursor.x);
|
||||
}
|
||||
|
||||
/*
|
||||
/!** Enable or disable cursor visibility *!/
|
||||
function cursorEnable(enable) {
|
||||
cursor.hidden = !enable;
|
||||
cursor.a &= enable;
|
||||
blit(cursorCell(), cursor.a);
|
||||
}
|
||||
|
||||
/!** Safely move cursor *!/
|
||||
function cursorSet(y, x) {
|
||||
// Hide and prevent from showing up during the move
|
||||
cursor.suppress = true;
|
||||
blit(cursorCell(), false);
|
||||
|
||||
cursor.x = x;
|
||||
cursor.y = y;
|
||||
|
||||
// Show again
|
||||
cursor.suppress = false;
|
||||
blit(cursorCell(), cursor.a);
|
||||
}
|
||||
*/
|
||||
|
||||
/** Update cell on display. inv = invert (for cursor) */
|
||||
function blit(cell, inv) {
|
||||
var e = cell.e, fg, bg;
|
||||
// Colors
|
||||
fg = inv ? cell.bg : cell.fg;
|
||||
bg = inv ? cell.fg : cell.bg;
|
||||
// Update
|
||||
e.innerText = (cell.t+' ')[0];
|
||||
e.className = 'fg'+fg+' bg'+bg;
|
||||
}
|
||||
|
||||
/** Show entire screen */
|
||||
function blitAll() {
|
||||
screen.forEach(function(cell, i) {
|
||||
/* Invert if under cursor & cursor active */
|
||||
var inv = cursor.a && (i == cursor.y*W+cursor.x);
|
||||
blit(cell, inv);
|
||||
});
|
||||
}
|
||||
|
||||
/** Load screen content from a 'binary' sequence */
|
||||
function load(obj) {
|
||||
cursor.x = obj.x;
|
||||
cursor.y = obj.y;
|
||||
cursor.hidden = !obj.cv;
|
||||
|
||||
// full re-init if size changed
|
||||
if (obj.w != W || obj.h != H) {
|
||||
Term.init(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
// Simple compression - hexFG hexBG 'ASCII' (r/s/t/u NUM{1,2,3,4})?
|
||||
// comma instead of both colors = same as before
|
||||
|
||||
var i = 0, ci = 0, str = obj.screen;
|
||||
var fg = 7, bg = 0;
|
||||
while(i < str.length && ci<W*H) {
|
||||
var cell = screen[ci++];
|
||||
|
||||
var j = str[i];
|
||||
if (j != ',') { // comma = repeat last colors
|
||||
fg = cell.fg = parseInt(str[i++], 16);
|
||||
bg = cell.bg = parseInt(str[i++], 16);
|
||||
} else {
|
||||
i++;
|
||||
cell.fg = fg;
|
||||
cell.bg = bg;
|
||||
}
|
||||
|
||||
var t = cell.t = str[i++];
|
||||
|
||||
var repchars = 0;
|
||||
switch(str[i]) {
|
||||
case 'r': repchars = 1; break;
|
||||
case 's': repchars = 2; break;
|
||||
case 't': repchars = 3; break;
|
||||
case 'u': repchars = 4; break;
|
||||
default: repchars = 0;
|
||||
}
|
||||
|
||||
if (repchars > 0) {
|
||||
var rep = parseInt(str.substr(i+1,repchars));
|
||||
i = i + repchars + 1;
|
||||
for (; rep>0 && ci<W*H; rep--) {
|
||||
cell = screen[ci++];
|
||||
cell.fg = fg;
|
||||
cell.bg = bg;
|
||||
cell.t = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blitAll();
|
||||
}
|
||||
|
||||
/** Init the terminal */
|
||||
function init(obj) {
|
||||
W = obj.w;
|
||||
H = obj.h;
|
||||
|
||||
/* Build screen & show */
|
||||
var e, cell, scr = qq('#screen');
|
||||
|
||||
// Empty the screen node
|
||||
while (scr.firstChild) scr.removeChild(scr.firstChild);
|
||||
|
||||
screen = [];
|
||||
|
||||
for(var i = 0; i < W*H; i++) {
|
||||
e = mk('span');
|
||||
|
||||
(function() {
|
||||
var x = i % W;
|
||||
var y = Math.floor(i / W);
|
||||
e.addEventListener('click', function () {
|
||||
Input.onTap(y, x);
|
||||
});
|
||||
})();
|
||||
|
||||
/* End of line */
|
||||
if ((i > 0) && (i % W == 0)) {
|
||||
scr.appendChild(mk('br'));
|
||||
}
|
||||
/* The cell */
|
||||
scr.appendChild(e);
|
||||
|
||||
cell = {t: ' ', fg: 7, bg: 0, e: e};
|
||||
screen.push(cell);
|
||||
blit(cell);
|
||||
}
|
||||
|
||||
/* Cursor blinking */
|
||||
clearInterval(blinkIval);
|
||||
blinkIval = setInterval(function() {
|
||||
cursor.a = !cursor.a;
|
||||
if (cursor.hidden) {
|
||||
cursor.a = false;
|
||||
}
|
||||
|
||||
if (!cursor.suppress) {
|
||||
blit(cursorCell(), cursor.a);
|
||||
}
|
||||
}, 500);
|
||||
|
||||
load(obj);
|
||||
}
|
||||
|
||||
// publish
|
||||
return {
|
||||
init: init,
|
||||
load: load
|
||||
};
|
||||
})();
|
||||
|
||||
/** Handle connections */
|
||||
var Conn = (function() {
|
||||
var ws;
|
||||
|
||||
function onOpen(evt) {
|
||||
console.log("CONNECTED");
|
||||
}
|
||||
|
||||
function onClose(evt) {
|
||||
console.warn("SOCKET CLOSED, code "+evt.code+". Reconnecting...");
|
||||
setTimeout(function() {
|
||||
init();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function onMessage(evt) {
|
||||
try {
|
||||
console.log("RX: ", evt.data);
|
||||
// Assume all our messages are screen updates
|
||||
Term.load(JSON.parse(evt.data));
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
function doSend(message) {
|
||||
console.log("TX: ", message);
|
||||
if (ws.readyState != 1) {
|
||||
console.error("Socket not ready");
|
||||
return;
|
||||
}
|
||||
if (typeof message != "string") {
|
||||
message = JSON.stringify(message);
|
||||
}
|
||||
ws.send(message);
|
||||
}
|
||||
|
||||
function init() {
|
||||
ws = new WebSocket("ws://"+_root+"/ws/update.cgi");
|
||||
ws.onopen = onOpen;
|
||||
ws.onclose = onClose;
|
||||
ws.onmessage = onMessage;
|
||||
|
||||
console.log("Opening socket.");
|
||||
}
|
||||
|
||||
return {
|
||||
ws: null,
|
||||
init: init,
|
||||
send: doSend
|
||||
};
|
||||
})();
|
||||
|
||||
//
|
||||
// Keyboard (& mouse) input
|
||||
//
|
||||
var Input = (function() {
|
||||
function sendStrMsg(str) {
|
||||
Conn.send("STR:"+str);
|
||||
}
|
||||
|
||||
function sendPosMsg(y, x) {
|
||||
Conn.send("TAP:"+y+','+x);
|
||||
}
|
||||
|
||||
function sendBtnMsg(n) {
|
||||
Conn.send("BTN:"+n);
|
||||
}
|
||||
|
||||
function init() {
|
||||
window.addEventListener('keypress', function(e) {
|
||||
var code = +e.which;
|
||||
if (code >= 32 && code < 127) {
|
||||
var ch = String.fromCharCode(code);
|
||||
//console.log("Typed ", ch, "code", code, e);
|
||||
sendStrMsg(ch);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('keydown', function(e) {
|
||||
var code = e.keyCode;
|
||||
//console.log("Down ", code, e);
|
||||
switch(code) {
|
||||
case 8: sendStrMsg('\x08'); break;
|
||||
case 13: sendStrMsg('\x0d\x0a'); break;
|
||||
case 27: sendStrMsg('\x1b'); break; // this allows to directly enter control sequences
|
||||
case 37: sendStrMsg('\x1b[D'); break;
|
||||
case 38: sendStrMsg('\x1b[A'); break;
|
||||
case 39: sendStrMsg('\x1b[C'); break;
|
||||
case 40: sendStrMsg('\x1b[B'); break;
|
||||
}
|
||||
});
|
||||
|
||||
qa('#buttons button').forEach(function(s) {
|
||||
s.addEventListener('click', function() {
|
||||
sendBtnMsg(+this.dataset['n']);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
onTap: sendPosMsg
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
window.termInit = function (obj) {
|
||||
Term.init(obj);
|
||||
Conn.init();
|
||||
Input.init();
|
||||
}
|
||||
})();
|
||||
Executable
+95
@@ -0,0 +1,95 @@
|
||||
/** Make a node */
|
||||
function mk(e) {return document.createElement(e)}
|
||||
|
||||
/** Find one by query */
|
||||
function qq(s) {return document.querySelector(s)}
|
||||
|
||||
/** Find all by query */
|
||||
function qa(s) {return document.querySelectorAll(s)}
|
||||
|
||||
/** Convert any to bool safely */
|
||||
function bool(x) {
|
||||
return (x === 1 || x === '1' || x === true || x === 'true');
|
||||
}
|
||||
|
||||
function intval(x) {
|
||||
return parseInt(x);
|
||||
}
|
||||
|
||||
/** 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, "\\$&");
|
||||
}
|
||||
|
||||
function numfmt(x, places) {
|
||||
var pow = Math.pow(10, places);
|
||||
return Math.round(x*pow) / pow;
|
||||
}
|
||||
|
||||
function estimateLoadTime(fs, n) {
|
||||
return (1000/fs)*n+1500;
|
||||
}
|
||||
|
||||
function msNow() {
|
||||
return +(new Date);
|
||||
}
|
||||
|
||||
function msElapsed(start) {
|
||||
return msNow() - start;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/** Wifi page */
|
||||
(function () {
|
||||
var authStr = ['Open', 'WEP', 'WPA', 'WPA2', 'WPA/WPA2'];
|
||||
var curSSID;
|
||||
|
||||
/** Update display for received response */
|
||||
function onScan(resp, status) {
|
||||
if (status != 200) {
|
||||
// bad response
|
||||
rescan(5000); // wait 5sm then retry
|
||||
return;
|
||||
}
|
||||
|
||||
resp = JSON.parse(resp);
|
||||
|
||||
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').remove();
|
||||
|
||||
$list.toggle(done);
|
||||
$('#ap-loader').toggle(!done);
|
||||
|
||||
// scan done
|
||||
resp.result.APs.sort(function (a, b) {
|
||||
return b.rssi - a.rssi;
|
||||
}).forEach(function (ap) {
|
||||
ap.enc = intval(ap.enc);
|
||||
|
||||
if (ap.enc > 4) return; // hide unsupported auths
|
||||
|
||||
var item = document.createElement('div');
|
||||
|
||||
var $item = $(item)
|
||||
.data('ssid', ap.essid)
|
||||
.data('pwd', ap.enc != 0)
|
||||
.addClass('AP');
|
||||
|
||||
// mark current SSID
|
||||
if (ap.essid == curSSID) {
|
||||
$item.addClass('selected');
|
||||
}
|
||||
|
||||
var inner = document.createElement('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);
|
||||
|
||||
// populate the form
|
||||
$('#conn-essid').val($th.data('ssid'));
|
||||
$('#conn-passwd').val(''); // clear
|
||||
|
||||
if ($th.data('pwd')) {
|
||||
// this AP needs a password
|
||||
Modal.show('#psk-modal');
|
||||
} else {
|
||||
Modal.show('#reset-modal');
|
||||
$('#conn-form').submit();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
item.appendChild(inner);
|
||||
$list[0].appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
/** Ask the CGI what APs are visible (async) */
|
||||
function scanAPs() {
|
||||
$.get('http://'+_root+'/wifi/scan', onScan);
|
||||
}
|
||||
|
||||
function rescan(time) {
|
||||
setTimeout(scanAPs, time);
|
||||
}
|
||||
|
||||
/** Set up the WiFi page */
|
||||
window.wifiInit = function (obj) {
|
||||
//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"},
|
||||
// ]
|
||||
// }
|
||||
//};
|
||||
|
||||
// Hide what should be hidden in this mode
|
||||
$('.x-hide-'+obj.mode).addClass('hidden');
|
||||
obj.mode = +obj.mode;
|
||||
|
||||
// Channel writable only in AP mode
|
||||
if (obj.mode != 2) $('#channel').attr('readonly', 1);
|
||||
|
||||
curSSID = obj.staSSID;
|
||||
|
||||
// add SSID to the opmode field
|
||||
if (curSSID) {
|
||||
var box = $('#opmodebox');
|
||||
box.html(box.html() + ' (' + curSSID + ')');
|
||||
}
|
||||
|
||||
// hide IP if IP not received
|
||||
if (!obj.staIP) $('.x-hide-noip').addClass('hidden');
|
||||
|
||||
// scan if not AP
|
||||
if (obj.mode != 2) {
|
||||
scanAPs();
|
||||
}
|
||||
|
||||
$('#modeswitch').html([
|
||||
'<a class="button" href="/wifi/setmode?mode=3">Client+AP</a> <a class="button" href="/wifi/setmode?mode=2">AP only</a>',
|
||||
'<a class="button" href="/wifi/setmode?mode=3">Client+AP</a>',
|
||||
'<a class="button" href="/wifi/setmode?mode=1">Client only</a> <a class="button" href="/wifi/setmode?mode=2">AP only</a>'
|
||||
][obj.mode-1]);
|
||||
};
|
||||
|
||||
window.wifiConn = function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var abortTmeo;
|
||||
|
||||
function getStatus() {
|
||||
xhr.open("GET", 'http://'+_root+"/wifi/connstatus");
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState == 4 && xhr.status >= 200 && xhr.status < 300) {
|
||||
clearTimeout(abortTmeo);
|
||||
var data = JSON.parse(xhr.responseText);
|
||||
var done = false;
|
||||
var msg = '...';
|
||||
|
||||
if (data.status == "idle") {
|
||||
msg = "Preparing to connect";
|
||||
}
|
||||
else if (data.status == "success") {
|
||||
msg = "Connected! Received IP " + data.ip + ".";
|
||||
done = true;
|
||||
}
|
||||
else if (data.status == "working") {
|
||||
msg = "Connecting to selected AP";
|
||||
}
|
||||
else if (data.status == "fail") {
|
||||
msg = "Connection failed, check your password and try again.";
|
||||
done = true;
|
||||
}
|
||||
|
||||
$("#status").html(msg);
|
||||
|
||||
if (done) {
|
||||
$('#backbtn').removeClass('hidden');
|
||||
$('.anim-dots').addClass('hidden');
|
||||
} else {
|
||||
window.setTimeout(getStatus, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
abortTmeo = setTimeout(function () {
|
||||
xhr.abort();
|
||||
$("#status").html("Telemetry lost, try reconnecting to the AP.");
|
||||
$('#backbtn').removeClass('hidden');
|
||||
$('.anim-dots').addClass('hidden');
|
||||
}, 4000);
|
||||
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
getStatus();
|
||||
};
|
||||
})();
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Packing js..."
|
||||
|
||||
cat jssrc/chibi.js \
|
||||
jssrc/utils.js \
|
||||
jssrc/modal.js \
|
||||
jssrc/appcommon.js \
|
||||
jssrc/term.js \
|
||||
jssrc/wifi.js > js/app.js
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
|
||||
// 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);
|
||||
@@ -0,0 +1,178 @@
|
||||
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;
|
||||
}
|
||||
|
||||
.Box {
|
||||
display: block;
|
||||
max-width: 900px;
|
||||
|
||||
margin-top: dist(0);
|
||||
padding: dist(-1) dist(0);
|
||||
|
||||
@include media($phone) {
|
||||
margin-top: dist(-1);
|
||||
padding: dist(-3) dist(-2);
|
||||
}
|
||||
//
|
||||
//h1 + & {
|
||||
// margin-top: 0;
|
||||
//}
|
||||
//
|
||||
//h2 {
|
||||
// margin-top: 0;
|
||||
//}
|
||||
|
||||
p:first-child {
|
||||
margin-top:0;
|
||||
}
|
||||
|
||||
border-radius: 3px;
|
||||
background-color: rgba(white, .07);
|
||||
|
||||
//&.wide {
|
||||
// width: initial;
|
||||
// max-width: initial;
|
||||
//}
|
||||
//
|
||||
//&.medium {
|
||||
// max-width: 1200px;
|
||||
//}
|
||||
//
|
||||
//.Valfield {
|
||||
// display: inline-block;
|
||||
// min-width: 10em;
|
||||
//}
|
||||
}
|
||||
|
||||
body {
|
||||
position: relative;
|
||||
|
||||
padding: dist(0);
|
||||
@include media($phone) {
|
||||
padding: dist(-1);
|
||||
}
|
||||
|
||||
overflow-y: auto;
|
||||
|
||||
& > * {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
h1,h2 {
|
||||
@include noselect();
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: fsize(6);
|
||||
margin-top: 0;
|
||||
margin-bottom: dist(0);
|
||||
|
||||
@include media($phone) {
|
||||
font-size: fsize(3);
|
||||
margin-bottom: dist(-1);
|
||||
}
|
||||
|
||||
@include media($tablet) {
|
||||
font-size: fsize(5);
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: fsize(2);
|
||||
margin-bottom: dist(-1);
|
||||
//&:first-child{margin-top:0}
|
||||
}
|
||||
|
||||
td, th {
|
||||
padding: dist(-2);
|
||||
white-space: nowrap;
|
||||
|
||||
@include media($phone) {
|
||||
padding: dist(-3);
|
||||
}
|
||||
}
|
||||
|
||||
tbody th {
|
||||
text-align: right;
|
||||
width: $form-label-w;
|
||||
color: $c-form-label-fg;
|
||||
|
||||
@include media($phone) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
tbody td {
|
||||
input[type="text"], input[type="number"] {
|
||||
width: 10em;
|
||||
|
||||
@include media($phone) {
|
||||
width: 8em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
ul > * {
|
||||
padding-top: .1em;
|
||||
padding-bottom: .1em;
|
||||
}
|
||||
|
||||
#botnav {
|
||||
padding-top: 1.5em;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
padding: 0 dist(-2);
|
||||
text-decoration: underline;
|
||||
|
||||
&, &:visited, &:link {
|
||||
color: #2e4d6e;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #5abfff;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
.Modal {
|
||||
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 }
|
||||
}
|
||||
|
||||
.Dialog {
|
||||
margin: dist(-1);
|
||||
padding: dist(0);
|
||||
overflow: hidden;
|
||||
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
flex: 0 1 30rem;
|
||||
//min-height: 15rem;
|
||||
|
||||
background: #1c1c1e;
|
||||
border-left: 6px solid $c-form-highlight-a;
|
||||
border-right: 6px solid $c-form-highlight-a;
|
||||
box-shadow: 0 0 2px 0 #434349, 0 0 6px 0 black;
|
||||
|
||||
border-radius: 6px;
|
||||
|
||||
h1,h2 {
|
||||
margin-top:0;
|
||||
}
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// "toast"
|
||||
.NotifyMsg {
|
||||
position: fixed;
|
||||
bottom: 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: #37a349;
|
||||
&.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 }
|
||||
}
|
||||
*/
|
||||
Executable
+439
@@ -0,0 +1,439 @@
|
||||
/* 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: 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;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
$term-colors:
|
||||
// 0 black, 1 red, 2 green, 3 yellow
|
||||
// 4 blue, 5 mag, 6 cyan, 7 white
|
||||
#111213, #CC0000, #4E9A06, #C4A000,
|
||||
#3465A4, #75507B, #06989A, #D3D7CF,
|
||||
// BRIGHT
|
||||
// 8 black, 9 red, 10 green, 11 yellow
|
||||
// 12 blue, 13 mag, 14 cyan, 15 white
|
||||
#555753, #EF2929, #8AE234, #FCE94F,
|
||||
#729FCF, #AD7FA8, #34E2E2, #EEEEEC;
|
||||
|
||||
@for $i from 1 through length($term-colors) {
|
||||
$c: nth($term-colors, $i);
|
||||
.fg#{$i - 1} { color: $c; }
|
||||
.bg#{$i - 1} { background-color: $c; }
|
||||
}
|
||||
|
||||
.fg8, .fg9, .fg10, .fg11, .fg12, .fg13, .fg14, .fg15 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nb {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
Executable
+55
@@ -0,0 +1,55 @@
|
||||
// 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;
|
||||
}
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
@import "normalize";
|
||||
@import "lib/bourbon/bourbon";
|
||||
|
||||
@import "grid-settings";
|
||||
@import "lib/neat/neat";
|
||||
|
||||
@import "utils";
|
||||
|
||||
$form-label-w: 130px;
|
||||
$form-label-gap: 8px;
|
||||
$form-field-w: 250px;
|
||||
|
||||
$c-form-label-fg: white;
|
||||
$c-form-field-bg: #303030;
|
||||
$c-form-field-fg: white;
|
||||
$c-form-highlight: #214e7a;
|
||||
$c-form-highlight-a: #2972ba;
|
||||
|
||||
@function dist($x) {
|
||||
@return modular-scale($x, 1rem, $golden);
|
||||
}
|
||||
|
||||
@function fsize($x) {
|
||||
@return modular-scale($x, 1em, $major-second);
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
[onclick] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@import "modal";
|
||||
@import "layout";
|
||||
@import "form/index";
|
||||
|
||||
// import all our pages
|
||||
@import "pages/wifi";
|
||||
@import "pages/term";
|
||||
@import "pages/about";
|
||||
@import "term-colors";
|
||||
|
||||
// media queries
|
||||
|
||||
@include media($tablet-min) {
|
||||
.mq-phone { display: none; }
|
||||
}
|
||||
|
||||
@include media($phone) {
|
||||
.mq-tablet-min { display: none; }
|
||||
}
|
||||
|
||||
@include media($normal-min) {
|
||||
.mq-tablet-max { display: none; }
|
||||
}
|
||||
|
||||
@include media($tablet-max) {
|
||||
.mq-normal-min { display: none; }
|
||||
}
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
@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;
|
||||
}
|
||||
|
||||
text-shadow: 1.5px 1.5px 2px rgba(black, 0.6);
|
||||
|
||||
@include fancy-btn-colors($btn-blue-f, $btn-blue-b, $btn-blue-fa, $btn-blue-ba);
|
||||
}
|
||||
|
||||
//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);
|
||||
//}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
|
||||
// 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));
|
||||
}
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
@import "buttons";
|
||||
|
||||
#{$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;
|
||||
}
|
||||
}
|
||||
|
||||
//#{$all-text-inputs} {
|
||||
// @include can-select();
|
||||
//}
|
||||
|
||||
//textarea {
|
||||
// font-family: monospace;
|
||||
// line-height: 1.2em;
|
||||
// display: block; // fixes weird bottom margin
|
||||
//}
|
||||
|
||||
//@import "select";
|
||||
Executable
+169
@@ -0,0 +1,169 @@
|
||||
// Unified Form wrapper
|
||||
form { @include naked(); }
|
||||
|
||||
#{$all-text-inputs}, select, label.select-wrap {
|
||||
width: $form-field-w;
|
||||
}
|
||||
|
||||
form .Row {
|
||||
vertical-align: middle;
|
||||
margin: 14px auto;
|
||||
text-align: left;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
width: $form-label-w;
|
||||
|
||||
@include media($phone) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.buttons {
|
||||
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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
// special phone style
|
||||
@include media($phone) {
|
||||
flex-direction: column;
|
||||
|
||||
&.buttons, &.centered {
|
||||
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}, textarea {
|
||||
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;
|
||||
}
|
||||
}
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
@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';
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
+411
@@ -0,0 +1,411 @@
|
||||
// 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
@@ -0,0 +1,87 @@
|
||||
// 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";
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
@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...);
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
@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;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
@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...);
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
@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
@@ -0,0 +1,64 @@
|
||||
@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;
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
@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;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
@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;
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
@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;
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/// 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
@@ -0,0 +1,26 @@
|
||||
@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
@@ -0,0 +1,26 @@
|
||||
@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...);
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Provides a quick method for setting an element’s position. Use a `null` value to “skip” a side.
|
||||
///
|
||||
/// @param {Position} $position [relative]
|
||||
/// A CSS position value
|
||||
///
|
||||
/// @param {Arglist} $coordinates [null null null null]
|
||||
/// List of values that correspond to the 4-value syntax for the edges of a box
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include position(absolute, 0 null null 10em);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// left: 10em;
|
||||
/// position: absolute;
|
||||
/// top: 0;
|
||||
/// }
|
||||
///
|
||||
/// @require {function} is-length
|
||||
/// @require {function} unpack
|
||||
|
||||
@mixin position($position: relative, $coordinates: null null null null) {
|
||||
@if type-of($position) == list {
|
||||
$coordinates: $position;
|
||||
$position: relative;
|
||||
}
|
||||
|
||||
$coordinates: unpack($coordinates);
|
||||
|
||||
$offsets: (
|
||||
top: nth($coordinates, 1),
|
||||
right: nth($coordinates, 2),
|
||||
bottom: nth($coordinates, 3),
|
||||
left: nth($coordinates, 4)
|
||||
);
|
||||
|
||||
position: $position;
|
||||
|
||||
@each $offset, $value in $offsets {
|
||||
@if is-length($value) {
|
||||
#{$offset}: $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// A mixin for generating vendor prefixes on non-standardized properties.
|
||||
///
|
||||
/// @param {String} $property
|
||||
/// Property to prefix
|
||||
///
|
||||
/// @param {*} $value
|
||||
/// Value to use
|
||||
///
|
||||
/// @param {List} $prefixes
|
||||
/// Prefixes to define
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include prefixer(border-radius, 10px, webkit ms spec);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// -webkit-border-radius: 10px;
|
||||
/// -moz-border-radius: 10px;
|
||||
/// border-radius: 10px;
|
||||
/// }
|
||||
///
|
||||
/// @require {variable} $prefix-for-webkit
|
||||
/// @require {variable} $prefix-for-mozilla
|
||||
/// @require {variable} $prefix-for-microsoft
|
||||
/// @require {variable} $prefix-for-opera
|
||||
/// @require {variable} $prefix-for-spec
|
||||
|
||||
@mixin prefixer($property, $value, $prefixes) {
|
||||
@each $prefix in $prefixes {
|
||||
@if $prefix == webkit {
|
||||
@if $prefix-for-webkit {
|
||||
-webkit-#{$property}: $value;
|
||||
}
|
||||
} @else if $prefix == moz {
|
||||
@if $prefix-for-mozilla {
|
||||
-moz-#{$property}: $value;
|
||||
}
|
||||
} @else if $prefix == ms {
|
||||
@if $prefix-for-microsoft {
|
||||
-ms-#{$property}: $value;
|
||||
}
|
||||
} @else if $prefix == o {
|
||||
@if $prefix-for-opera {
|
||||
-o-#{$property}: $value;
|
||||
}
|
||||
} @else if $prefix == spec {
|
||||
@if $prefix-for-spec {
|
||||
#{$property}: $value;
|
||||
}
|
||||
} @else {
|
||||
@warn "Unrecognized prefix: #{$prefix}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin disable-prefix-for-all() {
|
||||
$prefix-for-webkit: false !global;
|
||||
$prefix-for-mozilla: false !global;
|
||||
$prefix-for-microsoft: false !global;
|
||||
$prefix-for-opera: false !global;
|
||||
$prefix-for-spec: false !global;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
@mixin retina-image($filename, $background-size, $extension: png, $retina-filename: null, $retina-suffix: _2x, $asset-pipeline: $asset-pipeline) {
|
||||
@if $asset-pipeline {
|
||||
background-image: image-url("#{$filename}.#{$extension}");
|
||||
} @else {
|
||||
background-image: url("#{$filename}.#{$extension}");
|
||||
}
|
||||
|
||||
@include hidpi {
|
||||
@if $asset-pipeline {
|
||||
@if $retina-filename {
|
||||
background-image: image-url("#{$retina-filename}.#{$extension}");
|
||||
} @else {
|
||||
background-image: image-url("#{$filename}#{$retina-suffix}.#{$extension}");
|
||||
}
|
||||
} @else {
|
||||
@if $retina-filename {
|
||||
background-image: url("#{$retina-filename}.#{$extension}");
|
||||
} @else {
|
||||
background-image: url("#{$filename}#{$retina-suffix}.#{$extension}");
|
||||
}
|
||||
}
|
||||
|
||||
background-size: $background-size;
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Sets the `width` and `height` of the element.
|
||||
///
|
||||
/// @param {List} $size
|
||||
/// A list of at most 2 size values.
|
||||
///
|
||||
/// If there is only a single value in `$size` it is used for both width and height. All units are supported.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .first-element {
|
||||
/// @include size(2em);
|
||||
/// }
|
||||
///
|
||||
/// .second-element {
|
||||
/// @include size(auto 10em);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .first-element {
|
||||
/// width: 2em;
|
||||
/// height: 2em;
|
||||
/// }
|
||||
///
|
||||
/// .second-element {
|
||||
/// width: auto;
|
||||
/// height: 10em;
|
||||
/// }
|
||||
///
|
||||
/// @todo Refactor in 5.0.0 to use a comma-separated argument
|
||||
|
||||
@mixin size($value) {
|
||||
$width: nth($value, 1);
|
||||
$height: $width;
|
||||
|
||||
@if length($value) > 1 {
|
||||
$height: nth($value, 2);
|
||||
}
|
||||
|
||||
@if is-size($height) {
|
||||
height: $height;
|
||||
} @else {
|
||||
@warn "`#{$height}` is not a valid length for the `$height` parameter in the `size` mixin.";
|
||||
}
|
||||
|
||||
@if is-size($width) {
|
||||
width: $width;
|
||||
} @else {
|
||||
@warn "`#{$width}` is not a valid length for the `$width` parameter in the `size` mixin.";
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Generates variables for all text-based inputs. Please note that you must use interpolation on the variable: `#{$all-text-inputs}`.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// #{$all-text-inputs} {
|
||||
/// border: 1px solid #f00;
|
||||
/// }
|
||||
///
|
||||
/// #{$all-text-inputs-focus},
|
||||
/// #{$all-text-inputs-hover} {
|
||||
/// border: 1px solid #0f0;
|
||||
/// }
|
||||
///
|
||||
/// #{$all-text-inputs-active} {
|
||||
/// border: 1px solid #00f;
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// input[type="color"],
|
||||
/// input[type="date"],
|
||||
/// input[type="datetime"],
|
||||
/// input[type="datetime-local"],
|
||||
/// input[type="email"],
|
||||
/// input[type="month"],
|
||||
/// input[type="number"],
|
||||
/// input[type="password"],
|
||||
/// input[type="search"],
|
||||
/// input[type="tel"],
|
||||
/// input[type="text"],
|
||||
/// input[type="time"],
|
||||
/// input[type="url"],
|
||||
/// input[type="week"],
|
||||
/// textarea {
|
||||
/// border: 1px solid #f00;
|
||||
/// }
|
||||
///
|
||||
/// input[type="color"]:focus,
|
||||
/// input[type="date"]:focus,
|
||||
/// input[type="datetime"]:focus,
|
||||
/// input[type="datetime-local"]:focus,
|
||||
/// input[type="email"]:focus,
|
||||
/// input[type="month"]:focus,
|
||||
/// input[type="number"]:focus,
|
||||
/// input[type="password"]:focus,
|
||||
/// input[type="search"]:focus,
|
||||
/// input[type="tel"]:focus,
|
||||
/// input[type="text"]:focus,
|
||||
/// input[type="time"]:focus,
|
||||
/// input[type="url"]:focus,
|
||||
/// input[type="week"]:focus,
|
||||
/// textarea:focus,
|
||||
/// input[type="color"]:hover,
|
||||
/// input[type="date"]:hover,
|
||||
/// input[type="datetime"]:hover,
|
||||
/// input[type="datetime-local"]:hover,
|
||||
/// input[type="email"]:hover,
|
||||
/// input[type="month"]:hover,
|
||||
/// input[type="number"]:hover,
|
||||
/// input[type="password"]:hover,
|
||||
/// input[type="search"]:hover,
|
||||
/// input[type="tel"]:hover,
|
||||
/// input[type="text"]:hover,
|
||||
/// input[type="time"]:hover,
|
||||
/// input[type="url"]:hover,
|
||||
/// input[type="week"]:hover,
|
||||
/// textarea:hover {
|
||||
/// border: 1px solid #0f0;
|
||||
/// }
|
||||
///
|
||||
/// input[type="color"]:active,
|
||||
/// input[type="date"]:active,
|
||||
/// input[type="datetime"]:active,
|
||||
/// input[type="datetime-local"]:active,
|
||||
/// input[type="email"]:active,
|
||||
/// input[type="month"]:active,
|
||||
/// input[type="number"]:active,
|
||||
/// input[type="password"]:active,
|
||||
/// input[type="search"]:active,
|
||||
/// input[type="tel"]:active,
|
||||
/// input[type="text"]:active,
|
||||
/// input[type="time"]:active,
|
||||
/// input[type="url"]:active,
|
||||
/// input[type="week"]:active,
|
||||
/// textarea:active {
|
||||
/// border: 1px solid #00f;
|
||||
/// }
|
||||
///
|
||||
/// @require assign-inputs
|
||||
///
|
||||
/// @type List
|
||||
|
||||
$text-inputs-list: //'input[type="color"]',
|
||||
//'input[type="date"]',
|
||||
//'input[type="datetime"]',
|
||||
//'input[type="datetime-local"]',
|
||||
//'input[type="email"]',
|
||||
//'input[type="month"]',
|
||||
'input[type="number"]',
|
||||
'input[type="password"]',
|
||||
//'input[type="search"]',
|
||||
//'input[type="tel"]',
|
||||
'input[type="text"]',
|
||||
//'input[type="time"]',
|
||||
//'input[type="url"]',
|
||||
//'input[type="week"]',
|
||||
//'input:not([type])',
|
||||
'textarea';
|
||||
|
||||
$all-text-inputs: assign-inputs($text-inputs-list);
|
||||
$all-text-inputs-active: assign-inputs($text-inputs-list, active);
|
||||
$all-text-inputs-focus: assign-inputs($text-inputs-list, focus);
|
||||
$all-text-inputs-hover: assign-inputs($text-inputs-list, hover);
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// CSS cubic-bezier timing functions. Timing functions courtesy of jquery.easie (github.com/jaukia/easie)
|
||||
///
|
||||
/// Timing functions are the same as demoed here: http://jqueryui.com/resources/demos/effect/easing.html
|
||||
///
|
||||
/// @type cubic-bezier
|
||||
|
||||
$ease-in-quad: cubic-bezier(0.550, 0.085, 0.680, 0.530);
|
||||
$ease-in-cubic: cubic-bezier(0.550, 0.055, 0.675, 0.190);
|
||||
$ease-in-quart: cubic-bezier(0.895, 0.030, 0.685, 0.220);
|
||||
$ease-in-quint: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
$ease-in-sine: cubic-bezier(0.470, 0.000, 0.745, 0.715);
|
||||
$ease-in-expo: cubic-bezier(0.950, 0.050, 0.795, 0.035);
|
||||
$ease-in-circ: cubic-bezier(0.600, 0.040, 0.980, 0.335);
|
||||
$ease-in-back: cubic-bezier(0.600, -0.280, 0.735, 0.045);
|
||||
|
||||
$ease-out-quad: cubic-bezier(0.250, 0.460, 0.450, 0.940);
|
||||
$ease-out-cubic: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
$ease-out-quart: cubic-bezier(0.165, 0.840, 0.440, 1.000);
|
||||
$ease-out-quint: cubic-bezier(0.230, 1.000, 0.320, 1.000);
|
||||
$ease-out-sine: cubic-bezier(0.390, 0.575, 0.565, 1.000);
|
||||
$ease-out-expo: cubic-bezier(0.190, 1.000, 0.220, 1.000);
|
||||
$ease-out-circ: cubic-bezier(0.075, 0.820, 0.165, 1.000);
|
||||
$ease-out-back: cubic-bezier(0.175, 0.885, 0.320, 1.275);
|
||||
|
||||
$ease-in-out-quad: cubic-bezier(0.455, 0.030, 0.515, 0.955);
|
||||
$ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
$ease-in-out-quart: cubic-bezier(0.770, 0.000, 0.175, 1.000);
|
||||
$ease-in-out-quint: cubic-bezier(0.860, 0.000, 0.070, 1.000);
|
||||
$ease-in-out-sine: cubic-bezier(0.445, 0.050, 0.550, 0.950);
|
||||
$ease-in-out-expo: cubic-bezier(1.000, 0.000, 0.000, 1.000);
|
||||
$ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.150, 0.860);
|
||||
$ease-in-out-back: cubic-bezier(0.680, -0.550, 0.265, 1.550);
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
@mixin triangle($size, $color, $direction) {
|
||||
$width: nth($size, 1);
|
||||
$height: nth($size, length($size));
|
||||
$foreground-color: nth($color, 1);
|
||||
$background-color: if(length($color) == 2, nth($color, 2), transparent);
|
||||
height: 0;
|
||||
width: 0;
|
||||
|
||||
@if ($direction == up) or ($direction == down) or ($direction == right) or ($direction == left) {
|
||||
$width: $width / 2;
|
||||
$height: if(length($size) > 1, $height, $height/2);
|
||||
|
||||
@if $direction == up {
|
||||
border-bottom: $height solid $foreground-color;
|
||||
border-left: $width solid $background-color;
|
||||
border-right: $width solid $background-color;
|
||||
} @else if $direction == right {
|
||||
border-bottom: $width solid $background-color;
|
||||
border-left: $height solid $foreground-color;
|
||||
border-top: $width solid $background-color;
|
||||
} @else if $direction == down {
|
||||
border-left: $width solid $background-color;
|
||||
border-right: $width solid $background-color;
|
||||
border-top: $height solid $foreground-color;
|
||||
} @else if $direction == left {
|
||||
border-bottom: $width solid $background-color;
|
||||
border-right: $height solid $foreground-color;
|
||||
border-top: $width solid $background-color;
|
||||
}
|
||||
} @else if ($direction == up-right) or ($direction == up-left) {
|
||||
border-top: $height solid $foreground-color;
|
||||
|
||||
@if $direction == up-right {
|
||||
border-left: $width solid $background-color;
|
||||
} @else if $direction == up-left {
|
||||
border-right: $width solid $background-color;
|
||||
}
|
||||
} @else if ($direction == down-right) or ($direction == down-left) {
|
||||
border-bottom: $height solid $foreground-color;
|
||||
|
||||
@if $direction == down-right {
|
||||
border-left: $width solid $background-color;
|
||||
} @else if $direction == down-left {
|
||||
border-right: $width solid $background-color;
|
||||
}
|
||||
} @else if ($direction == inset-up) {
|
||||
border-color: $background-color $background-color $foreground-color;
|
||||
border-style: solid;
|
||||
border-width: $height $width;
|
||||
} @else if ($direction == inset-down) {
|
||||
border-color: $foreground-color $background-color $background-color;
|
||||
border-style: solid;
|
||||
border-width: $height $width;
|
||||
} @else if ($direction == inset-right) {
|
||||
border-color: $background-color $background-color $background-color $foreground-color;
|
||||
border-style: solid;
|
||||
border-width: $width $height;
|
||||
} @else if ($direction == inset-left) {
|
||||
border-color: $background-color $foreground-color $background-color $background-color;
|
||||
border-style: solid;
|
||||
border-width: $width $height;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Provides an easy way to change the `word-wrap` property.
|
||||
///
|
||||
/// @param {String} $wrap [break-word]
|
||||
/// Value for the `word-break` property.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .wrapper {
|
||||
/// @include word-wrap(break-word);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .wrapper {
|
||||
/// overflow-wrap: break-word;
|
||||
/// word-break: break-all;
|
||||
/// word-wrap: break-word;
|
||||
/// }
|
||||
|
||||
@mixin word-wrap($wrap: break-word) {
|
||||
overflow-wrap: $wrap;
|
||||
word-wrap: $wrap;
|
||||
|
||||
@if $wrap == break-word {
|
||||
word-break: break-all;
|
||||
} @else {
|
||||
word-break: $wrap;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// http://www.w3.org/TR/css3-animations/#the-animation-name-property-
|
||||
// Each of these mixins support comma separated lists of values, which allows different transitions for individual properties to be described in a single style rule. Each value in the list corresponds to the value at that same position in the other properties.
|
||||
|
||||
@mixin animation($animations...) {
|
||||
@include prefixer(animation, $animations, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-name($names...) {
|
||||
@include prefixer(animation-name, $names, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-duration($times...) {
|
||||
@include prefixer(animation-duration, $times, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-timing-function($motions...) {
|
||||
// ease | linear | ease-in | ease-out | ease-in-out
|
||||
@include prefixer(animation-timing-function, $motions, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-iteration-count($values...) {
|
||||
// infinite | <number>
|
||||
@include prefixer(animation-iteration-count, $values, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-direction($directions...) {
|
||||
// normal | alternate
|
||||
@include prefixer(animation-direction, $directions, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-play-state($states...) {
|
||||
// running | paused
|
||||
@include prefixer(animation-play-state, $states, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-delay($times...) {
|
||||
@include prefixer(animation-delay, $times, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-fill-mode($modes...) {
|
||||
// none | forwards | backwards | both
|
||||
@include prefixer(animation-fill-mode, $modes, webkit moz spec);
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
@mixin appearance($value) {
|
||||
@include prefixer(appearance, $value, webkit moz ms o spec);
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
@mixin backface-visibility($visibility) {
|
||||
@include prefixer(backface-visibility, $visibility, webkit spec);
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
//************************************************************************//
|
||||
// Background-image property for adding multiple background images with
|
||||
// gradients, or for stringing multiple gradients together.
|
||||
//************************************************************************//
|
||||
|
||||
@mixin background-image($images...) {
|
||||
$webkit-images: ();
|
||||
$spec-images: ();
|
||||
|
||||
@each $image in $images {
|
||||
$webkit-image: ();
|
||||
$spec-image: ();
|
||||
|
||||
@if (type-of($image) == string) {
|
||||
$url-str: str-slice($image, 1, 3);
|
||||
$gradient-type: str-slice($image, 1, 6);
|
||||
|
||||
@if $url-str == "url" {
|
||||
$webkit-image: $image;
|
||||
$spec-image: $image;
|
||||
}
|
||||
|
||||
@else if $gradient-type == "linear" {
|
||||
$gradients: _linear-gradient-parser($image);
|
||||
$webkit-image: map-get($gradients, webkit-image);
|
||||
$spec-image: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else if $gradient-type == "radial" {
|
||||
$gradients: _radial-gradient-parser($image);
|
||||
$webkit-image: map-get($gradients, webkit-image);
|
||||
$spec-image: map-get($gradients, spec-image);
|
||||
}
|
||||
}
|
||||
|
||||
$webkit-images: append($webkit-images, $webkit-image, comma);
|
||||
$spec-images: append($spec-images, $spec-image, comma);
|
||||
}
|
||||
|
||||
background-image: $webkit-images;
|
||||
background-image: $spec-images;
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
//************************************************************************//
|
||||
// Background property for adding multiple backgrounds using shorthand
|
||||
// notation.
|
||||
//************************************************************************//
|
||||
|
||||
@mixin background($backgrounds...) {
|
||||
$webkit-backgrounds: ();
|
||||
$spec-backgrounds: ();
|
||||
|
||||
@each $background in $backgrounds {
|
||||
$webkit-background: ();
|
||||
$spec-background: ();
|
||||
$background-type: type-of($background);
|
||||
|
||||
@if $background-type == string or $background-type == list {
|
||||
$background-str: if($background-type == list, nth($background, 1), $background);
|
||||
|
||||
$url-str: str-slice($background-str, 1, 3);
|
||||
$gradient-type: str-slice($background-str, 1, 6);
|
||||
|
||||
@if $url-str == "url" {
|
||||
$webkit-background: $background;
|
||||
$spec-background: $background;
|
||||
}
|
||||
|
||||
@else if $gradient-type == "linear" {
|
||||
$gradients: _linear-gradient-parser("#{$background}");
|
||||
$webkit-background: map-get($gradients, webkit-image);
|
||||
$spec-background: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else if $gradient-type == "radial" {
|
||||
$gradients: _radial-gradient-parser("#{$background}");
|
||||
$webkit-background: map-get($gradients, webkit-image);
|
||||
$spec-background: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else {
|
||||
$webkit-background: $background;
|
||||
$spec-background: $background;
|
||||
}
|
||||
}
|
||||
|
||||
@else {
|
||||
$webkit-background: $background;
|
||||
$spec-background: $background;
|
||||
}
|
||||
|
||||
$webkit-backgrounds: append($webkit-backgrounds, $webkit-background, comma);
|
||||
$spec-backgrounds: append($spec-backgrounds, $spec-background, comma);
|
||||
}
|
||||
|
||||
background: $webkit-backgrounds;
|
||||
background: $spec-backgrounds;
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
@mixin border-image($borders...) {
|
||||
$webkit-borders: ();
|
||||
$spec-borders: ();
|
||||
|
||||
@each $border in $borders {
|
||||
$webkit-border: ();
|
||||
$spec-border: ();
|
||||
$border-type: type-of($border);
|
||||
|
||||
@if $border-type == string or list {
|
||||
$border-str: if($border-type == list, nth($border, 1), $border);
|
||||
|
||||
$url-str: str-slice($border-str, 1, 3);
|
||||
$gradient-type: str-slice($border-str, 1, 6);
|
||||
|
||||
@if $url-str == "url" {
|
||||
$webkit-border: $border;
|
||||
$spec-border: $border;
|
||||
}
|
||||
|
||||
@else if $gradient-type == "linear" {
|
||||
$gradients: _linear-gradient-parser("#{$border}");
|
||||
$webkit-border: map-get($gradients, webkit-image);
|
||||
$spec-border: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else if $gradient-type == "radial" {
|
||||
$gradients: _radial-gradient-parser("#{$border}");
|
||||
$webkit-border: map-get($gradients, webkit-image);
|
||||
$spec-border: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else {
|
||||
$webkit-border: $border;
|
||||
$spec-border: $border;
|
||||
}
|
||||
}
|
||||
|
||||
@else {
|
||||
$webkit-border: $border;
|
||||
$spec-border: $border;
|
||||
}
|
||||
|
||||
$webkit-borders: append($webkit-borders, $webkit-border, comma);
|
||||
$spec-borders: append($spec-borders, $spec-border, comma);
|
||||
}
|
||||
|
||||
-webkit-border-image: $webkit-borders;
|
||||
border-image: $spec-borders;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
//Examples:
|
||||
// @include border-image(url("image.png"));
|
||||
// @include border-image(url("image.png") 20 stretch);
|
||||
// @include border-image(linear-gradient(45deg, orange, yellow));
|
||||
// @include border-image(linear-gradient(45deg, orange, yellow) stretch);
|
||||
// @include border-image(linear-gradient(45deg, orange, yellow) 20 30 40 50 stretch round);
|
||||
// @include border-image(radial-gradient(top, cover, orange, yellow, orange));
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
@mixin calc($property, $value) {
|
||||
#{$property}: -webkit-calc(#{$value});
|
||||
#{$property}: calc(#{$value});
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
@mixin columns($arg: auto) {
|
||||
// <column-count> || <column-width>
|
||||
@include prefixer(columns, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-count($int: auto) {
|
||||
// auto || integer
|
||||
@include prefixer(column-count, $int, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-gap($length: normal) {
|
||||
// normal || length
|
||||
@include prefixer(column-gap, $length, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-fill($arg: auto) {
|
||||
// auto || length
|
||||
@include prefixer(column-fill, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule($arg) {
|
||||
// <border-width> || <border-style> || <color>
|
||||
@include prefixer(column-rule, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule-color($color) {
|
||||
@include prefixer(column-rule-color, $color, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule-style($style: none) {
|
||||
// none | hidden | dashed | dotted | double | groove | inset | inset | outset | ridge | solid
|
||||
@include prefixer(column-rule-style, $style, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule-width ($width: none) {
|
||||
@include prefixer(column-rule-width, $width, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-span($arg: none) {
|
||||
// none || all
|
||||
@include prefixer(column-span, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-width($length: auto) {
|
||||
// auto || length
|
||||
@include prefixer(column-width, $length, webkit moz spec);
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
@mixin filter($function: none) {
|
||||
// <filter-function> [<filter-function]* | none
|
||||
@include prefixer(filter, $function, webkit spec);
|
||||
}
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
// CSS3 Flexible Box Model and property defaults
|
||||
|
||||
// Custom shorthand notation for flexbox
|
||||
@mixin box($orient: inline-axis, $pack: start, $align: stretch) {
|
||||
@include display-box;
|
||||
@include box-orient($orient);
|
||||
@include box-pack($pack);
|
||||
@include box-align($align);
|
||||
}
|
||||
|
||||
@mixin display-box {
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox; // IE 10
|
||||
display: box;
|
||||
}
|
||||
|
||||
@mixin box-orient($orient: inline-axis) {
|
||||
// horizontal|vertical|inline-axis|block-axis|inherit
|
||||
@include prefixer(box-orient, $orient, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-pack($pack: start) {
|
||||
// start|end|center|justify
|
||||
@include prefixer(box-pack, $pack, webkit moz spec);
|
||||
-ms-flex-pack: $pack; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-align($align: stretch) {
|
||||
// start|end|center|baseline|stretch
|
||||
@include prefixer(box-align, $align, webkit moz spec);
|
||||
-ms-flex-align: $align; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-direction($direction: normal) {
|
||||
// normal|reverse|inherit
|
||||
@include prefixer(box-direction, $direction, webkit moz spec);
|
||||
-ms-flex-direction: $direction; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-lines($lines: single) {
|
||||
// single|multiple
|
||||
@include prefixer(box-lines, $lines, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-ordinal-group($int: 1) {
|
||||
@include prefixer(box-ordinal-group, $int, webkit moz spec);
|
||||
-ms-flex-order: $int; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-flex($value: 0) {
|
||||
@include prefixer(box-flex, $value, webkit moz spec);
|
||||
-ms-flex: $value; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-flex-group($int: 1) {
|
||||
@include prefixer(box-flex-group, $int, webkit moz spec);
|
||||
}
|
||||
|
||||
// CSS3 Flexible Box Model and property defaults
|
||||
// Unified attributes for 2009, 2011, and 2012 flavours.
|
||||
|
||||
// 2009 - display (box | inline-box)
|
||||
// 2011 - display (flexbox | inline-flexbox)
|
||||
// 2012 - display (flex | inline-flex)
|
||||
@mixin display($value) {
|
||||
// flex | inline-flex
|
||||
@if $value == "flex" {
|
||||
// 2009
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: box;
|
||||
|
||||
// 2012
|
||||
display: -webkit-flex;
|
||||
display: -moz-flex;
|
||||
display: -ms-flexbox; // 2011 (IE 10)
|
||||
display: flex;
|
||||
} @else if $value == "inline-flex" {
|
||||
display: -webkit-inline-box;
|
||||
display: -moz-inline-box;
|
||||
display: inline-box;
|
||||
|
||||
display: -webkit-inline-flex;
|
||||
display: -moz-inline-flex;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
} @else {
|
||||
display: $value;
|
||||
}
|
||||
}
|
||||
|
||||
// 2009 - box-flex (integer)
|
||||
// 2011 - flex (decimal | width decimal)
|
||||
// 2012 - flex (integer integer width)
|
||||
@mixin flex($value) {
|
||||
|
||||
// Grab flex-grow for older browsers.
|
||||
$flex-grow: nth($value, 1);
|
||||
|
||||
// 2009
|
||||
@include prefixer(box-flex, $flex-grow, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10), 2012
|
||||
@include prefixer(flex, $value, webkit moz ms spec);
|
||||
}
|
||||
|
||||
// 2009 - box-orient ( horizontal | vertical | inline-axis | block-axis)
|
||||
// - box-direction (normal | reverse)
|
||||
// 2011 - flex-direction (row | row-reverse | column | column-reverse)
|
||||
// 2012 - flex-direction (row | row-reverse | column | column-reverse)
|
||||
@mixin flex-direction($value: row) {
|
||||
|
||||
// Alt values.
|
||||
$value-2009: $value;
|
||||
$value-2011: $value;
|
||||
$direction: normal;
|
||||
|
||||
@if $value == row {
|
||||
$value-2009: horizontal;
|
||||
} @else if $value == "row-reverse" {
|
||||
$value-2009: horizontal;
|
||||
$direction: reverse;
|
||||
} @else if $value == column {
|
||||
$value-2009: vertical;
|
||||
} @else if $value == "column-reverse" {
|
||||
$value-2009: vertical;
|
||||
$direction: reverse;
|
||||
}
|
||||
|
||||
// 2009
|
||||
@include prefixer(box-orient, $value-2009, webkit moz spec);
|
||||
@include prefixer(box-direction, $direction, webkit moz spec);
|
||||
|
||||
// 2012
|
||||
@include prefixer(flex-direction, $value, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-direction: $value;
|
||||
}
|
||||
|
||||
// 2009 - box-lines (single | multiple)
|
||||
// 2011 - flex-wrap (nowrap | wrap | wrap-reverse)
|
||||
// 2012 - flex-wrap (nowrap | wrap | wrap-reverse)
|
||||
@mixin flex-wrap($value: nowrap) {
|
||||
// Alt values
|
||||
$alt-value: $value;
|
||||
@if $value == nowrap {
|
||||
$alt-value: single;
|
||||
} @else if $value == wrap {
|
||||
$alt-value: multiple;
|
||||
} @else if $value == "wrap-reverse" {
|
||||
$alt-value: multiple;
|
||||
}
|
||||
|
||||
@include prefixer(box-lines, $alt-value, webkit moz spec);
|
||||
@include prefixer(flex-wrap, $value, webkit moz ms spec);
|
||||
}
|
||||
|
||||
// 2009 - TODO: parse values into flex-direction/flex-wrap
|
||||
// 2011 - TODO: parse values into flex-direction/flex-wrap
|
||||
// 2012 - flex-flow (flex-direction || flex-wrap)
|
||||
@mixin flex-flow($value) {
|
||||
@include prefixer(flex-flow, $value, webkit moz spec);
|
||||
}
|
||||
|
||||
// 2009 - box-ordinal-group (integer)
|
||||
// 2011 - flex-order (integer)
|
||||
// 2012 - order (integer)
|
||||
@mixin order($int: 0) {
|
||||
// 2009
|
||||
@include prefixer(box-ordinal-group, $int, webkit moz spec);
|
||||
|
||||
// 2012
|
||||
@include prefixer(order, $int, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-order: $int;
|
||||
}
|
||||
|
||||
// 2012 - flex-grow (number)
|
||||
@mixin flex-grow($number: 0) {
|
||||
@include prefixer(flex-grow, $number, webkit moz spec);
|
||||
-ms-flex-positive: $number;
|
||||
}
|
||||
|
||||
// 2012 - flex-shrink (number)
|
||||
@mixin flex-shrink($number: 1) {
|
||||
@include prefixer(flex-shrink, $number, webkit moz spec);
|
||||
-ms-flex-negative: $number;
|
||||
}
|
||||
|
||||
// 2012 - flex-basis (number)
|
||||
@mixin flex-basis($width: auto) {
|
||||
@include prefixer(flex-basis, $width, webkit moz spec);
|
||||
-ms-flex-preferred-size: $width;
|
||||
}
|
||||
|
||||
// 2009 - box-pack (start | end | center | justify)
|
||||
// 2011 - flex-pack (start | end | center | justify)
|
||||
// 2012 - justify-content (flex-start | flex-end | center | space-between | space-around)
|
||||
@mixin justify-content($value: flex-start) {
|
||||
|
||||
// Alt values.
|
||||
$alt-value: $value;
|
||||
@if $value == "flex-start" {
|
||||
$alt-value: start;
|
||||
} @else if $value == "flex-end" {
|
||||
$alt-value: end;
|
||||
} @else if $value == "space-between" {
|
||||
$alt-value: justify;
|
||||
} @else if $value == "space-around" {
|
||||
$alt-value: distribute;
|
||||
}
|
||||
|
||||
// 2009
|
||||
@include prefixer(box-pack, $alt-value, webkit moz spec);
|
||||
|
||||
// 2012
|
||||
@include prefixer(justify-content, $value, webkit moz ms o spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-pack: $alt-value;
|
||||
}
|
||||
|
||||
// 2009 - box-align (start | end | center | baseline | stretch)
|
||||
// 2011 - flex-align (start | end | center | baseline | stretch)
|
||||
// 2012 - align-items (flex-start | flex-end | center | baseline | stretch)
|
||||
@mixin align-items($value: stretch) {
|
||||
|
||||
$alt-value: $value;
|
||||
|
||||
@if $value == "flex-start" {
|
||||
$alt-value: start;
|
||||
} @else if $value == "flex-end" {
|
||||
$alt-value: end;
|
||||
}
|
||||
|
||||
// 2009
|
||||
@include prefixer(box-align, $alt-value, webkit moz spec);
|
||||
|
||||
// 2012
|
||||
@include prefixer(align-items, $value, webkit moz ms o spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-align: $alt-value;
|
||||
}
|
||||
|
||||
// 2011 - flex-item-align (auto | start | end | center | baseline | stretch)
|
||||
// 2012 - align-self (auto | flex-start | flex-end | center | baseline | stretch)
|
||||
@mixin align-self($value: auto) {
|
||||
|
||||
$value-2011: $value;
|
||||
@if $value == "flex-start" {
|
||||
$value-2011: start;
|
||||
} @else if $value == "flex-end" {
|
||||
$value-2011: end;
|
||||
}
|
||||
|
||||
// 2012
|
||||
@include prefixer(align-self, $value, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-item-align: $value-2011;
|
||||
}
|
||||
|
||||
// 2011 - flex-line-pack (start | end | center | justify | distribute | stretch)
|
||||
// 2012 - align-content (flex-start | flex-end | center | space-between | space-around | stretch)
|
||||
@mixin align-content($value: stretch) {
|
||||
|
||||
$value-2011: $value;
|
||||
@if $value == "flex-start" {
|
||||
$value-2011: start;
|
||||
} @else if $value == "flex-end" {
|
||||
$value-2011: end;
|
||||
} @else if $value == "space-between" {
|
||||
$value-2011: justify;
|
||||
} @else if $value == "space-around" {
|
||||
$value-2011: distribute;
|
||||
}
|
||||
|
||||
// 2012
|
||||
@include prefixer(align-content, $value, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-line-pack: $value-2011;
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
@mixin font-face(
|
||||
$font-family,
|
||||
$file-path,
|
||||
$weight: normal,
|
||||
$style: normal,
|
||||
$asset-pipeline: $asset-pipeline,
|
||||
$file-formats: eot woff2 woff ttf svg) {
|
||||
|
||||
$font-url-prefix: font-url-prefixer($asset-pipeline);
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family;
|
||||
font-style: $style;
|
||||
font-weight: $weight;
|
||||
|
||||
src: font-source-declaration(
|
||||
$font-family,
|
||||
$file-path,
|
||||
$asset-pipeline,
|
||||
$file-formats,
|
||||
$font-url-prefix
|
||||
);
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
@mixin font-feature-settings($settings...) {
|
||||
@if length($settings) == 0 { $settings: none; }
|
||||
@include prefixer(font-feature-settings, $settings, webkit moz ms spec);
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// HiDPI mixin. Default value set to 1.3 to target Google Nexus 7 (http://bjango.com/articles/min-device-pixel-ratio/)
|
||||
@mixin hidpi($ratio: 1.3) {
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: $ratio),
|
||||
only screen and (min--moz-device-pixel-ratio: $ratio),
|
||||
only screen and (-o-min-device-pixel-ratio: #{$ratio}/1),
|
||||
only screen and (min-resolution: round($ratio * 96dpi)),
|
||||
only screen and (min-resolution: $ratio * 1dppx) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
@mixin hyphens($hyphenation: none) {
|
||||
// none | manual | auto
|
||||
@include prefixer(hyphens, $hyphenation, webkit moz ms spec);
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
@mixin image-rendering ($mode:auto) {
|
||||
|
||||
@if ($mode == crisp-edges) {
|
||||
-ms-interpolation-mode: nearest-neighbor; // IE8+
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
|
||||
@else {
|
||||
image-rendering: $mode;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// Adds keyframes blocks for supported prefixes, removing redundant prefixes in the block's content
|
||||
@mixin keyframes($name) {
|
||||
$original-prefix-for-webkit: $prefix-for-webkit;
|
||||
$original-prefix-for-mozilla: $prefix-for-mozilla;
|
||||
$original-prefix-for-microsoft: $prefix-for-microsoft;
|
||||
$original-prefix-for-opera: $prefix-for-opera;
|
||||
$original-prefix-for-spec: $prefix-for-spec;
|
||||
|
||||
@if $original-prefix-for-webkit {
|
||||
@include disable-prefix-for-all();
|
||||
$prefix-for-webkit: true !global;
|
||||
@-webkit-keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@if $original-prefix-for-mozilla {
|
||||
@include disable-prefix-for-all();
|
||||
$prefix-for-mozilla: true !global;
|
||||
@-moz-keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
$prefix-for-webkit: $original-prefix-for-webkit !global;
|
||||
$prefix-for-mozilla: $original-prefix-for-mozilla !global;
|
||||
$prefix-for-microsoft: $original-prefix-for-microsoft !global;
|
||||
$prefix-for-opera: $original-prefix-for-opera !global;
|
||||
$prefix-for-spec: $original-prefix-for-spec !global;
|
||||
|
||||
@if $original-prefix-for-spec {
|
||||
@keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
@mixin linear-gradient($pos, $g1, $g2: null,
|
||||
$g3: null, $g4: null,
|
||||
$g5: null, $g6: null,
|
||||
$g7: null, $g8: null,
|
||||
$g9: null, $g10: null,
|
||||
$fallback: null) {
|
||||
// Detect what type of value exists in $pos
|
||||
$pos-type: type-of(nth($pos, 1));
|
||||
$pos-spec: null;
|
||||
$pos-degree: null;
|
||||
|
||||
// If $pos is missing from mixin, reassign vars and add default position
|
||||
@if ($pos-type == color) or (nth($pos, 1) == "transparent") {
|
||||
$g10: $g9; $g9: $g8; $g8: $g7; $g7: $g6; $g6: $g5;
|
||||
$g5: $g4; $g4: $g3; $g3: $g2; $g2: $g1; $g1: $pos;
|
||||
$pos: null;
|
||||
}
|
||||
|
||||
@if $pos {
|
||||
$positions: _linear-positions-parser($pos);
|
||||
$pos-degree: nth($positions, 1);
|
||||
$pos-spec: nth($positions, 2);
|
||||
}
|
||||
|
||||
$full: $g1, $g2, $g3, $g4, $g5, $g6, $g7, $g8, $g9, $g10;
|
||||
|
||||
// Set $g1 as the default fallback color
|
||||
$fallback-color: nth($g1, 1);
|
||||
|
||||
// If $fallback is a color use that color as the fallback color
|
||||
@if (type-of($fallback) == color) or ($fallback == "transparent") {
|
||||
$fallback-color: $fallback;
|
||||
}
|
||||
|
||||
background-color: $fallback-color;
|
||||
background-image: -webkit-linear-gradient($pos-degree $full); // Safari 5.1+, Chrome
|
||||
background-image: unquote("linear-gradient(#{$pos-spec}#{$full})");
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
@mixin perspective($depth: none) {
|
||||
// none | <length>
|
||||
@include prefixer(perspective, $depth, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin perspective-origin($value: 50% 50%) {
|
||||
@include prefixer(perspective-origin, $value, webkit moz spec);
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
@mixin placeholder {
|
||||
$placeholders: ":-webkit-input" ":-moz" "-moz" "-ms-input";
|
||||
@each $placeholder in $placeholders {
|
||||
&:#{$placeholder}-placeholder {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// Requires Sass 3.1+
|
||||
@mixin radial-gradient($g1, $g2,
|
||||
$g3: null, $g4: null,
|
||||
$g5: null, $g6: null,
|
||||
$g7: null, $g8: null,
|
||||
$g9: null, $g10: null,
|
||||
$pos: null,
|
||||
$shape-size: null,
|
||||
$fallback: null) {
|
||||
|
||||
$data: _radial-arg-parser($g1, $g2, $pos, $shape-size);
|
||||
$g1: nth($data, 1);
|
||||
$g2: nth($data, 2);
|
||||
$pos: nth($data, 3);
|
||||
$shape-size: nth($data, 4);
|
||||
|
||||
$full: $g1, $g2, $g3, $g4, $g5, $g6, $g7, $g8, $g9, $g10;
|
||||
|
||||
// Strip deprecated cover/contain for spec
|
||||
$shape-size-spec: _shape-size-stripper($shape-size);
|
||||
|
||||
// Set $g1 as the default fallback color
|
||||
$first-color: nth($full, 1);
|
||||
$fallback-color: nth($first-color, 1);
|
||||
|
||||
@if (type-of($fallback) == color) or ($fallback == "transparent") {
|
||||
$fallback-color: $fallback;
|
||||
}
|
||||
|
||||
// Add Commas and spaces
|
||||
$shape-size: if($shape-size, "#{$shape-size}, ", null);
|
||||
$pos: if($pos, "#{$pos}, ", null);
|
||||
$pos-spec: if($pos, "at #{$pos}", null);
|
||||
$shape-size-spec: if(($shape-size-spec != " ") and ($pos == null), "#{$shape-size-spec}, ", "#{$shape-size-spec} ");
|
||||
|
||||
background-color: $fallback-color;
|
||||
background-image: -webkit-radial-gradient(unquote(#{$pos}#{$shape-size}#{$full}));
|
||||
background-image: unquote("radial-gradient(#{$shape-size-spec}#{$pos-spec}#{$full})");
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Outputs the spec and prefixed versions of the `::selection` pseudo-element.
|
||||
///
|
||||
/// @param {Bool} $current-selector [false]
|
||||
/// If set to `true`, it takes the current element into consideration.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include selection(true) {
|
||||
/// background-color: #ffbb52;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element::-moz-selection {
|
||||
/// background-color: #ffbb52;
|
||||
/// }
|
||||
///
|
||||
/// .element::selection {
|
||||
/// background-color: #ffbb52;
|
||||
/// }
|
||||
|
||||
@mixin selection($current-selector: false) {
|
||||
@if $current-selector {
|
||||
&::-moz-selection {
|
||||
@content;
|
||||
}
|
||||
|
||||
&::selection {
|
||||
@content;
|
||||
}
|
||||
} @else {
|
||||
::-moz-selection {
|
||||
@content;
|
||||
}
|
||||
|
||||
::selection {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
@mixin text-decoration($value) {
|
||||
// <text-decoration-line> || <text-decoration-style> || <text-decoration-color>
|
||||
@include prefixer(text-decoration, $value, moz);
|
||||
}
|
||||
|
||||
@mixin text-decoration-line($line: none) {
|
||||
// none || underline || overline || line-through
|
||||
@include prefixer(text-decoration-line, $line, moz);
|
||||
}
|
||||
|
||||
@mixin text-decoration-style($style: solid) {
|
||||
// solid || double || dotted || dashed || wavy
|
||||
@include prefixer(text-decoration-style, $style, moz webkit);
|
||||
}
|
||||
|
||||
@mixin text-decoration-color($color: currentColor) {
|
||||
// currentColor || <color>
|
||||
@include prefixer(text-decoration-color, $color, moz);
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
@mixin transform($property: none) {
|
||||
// none | <transform-function>
|
||||
@include prefixer(transform, $property, webkit moz ms o spec);
|
||||
}
|
||||
|
||||
@mixin transform-origin($axes: 50%) {
|
||||
// x-axis - left | center | right | length | %
|
||||
// y-axis - top | center | bottom | length | %
|
||||
// z-axis - length
|
||||
@include prefixer(transform-origin, $axes, webkit moz ms o spec);
|
||||
}
|
||||
|
||||
@mixin transform-style($style: flat) {
|
||||
@include prefixer(transform-style, $style, webkit moz ms o spec);
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
// Shorthand mixin. Supports multiple parentheses-deliminated values for each variable.
|
||||
// Example: @include transition (all 2s ease-in-out);
|
||||
// @include transition (opacity 1s ease-in 2s, width 2s ease-out);
|
||||
// @include transition-property (transform, opacity);
|
||||
|
||||
@mixin transition($properties...) {
|
||||
// Fix for vendor-prefix transform property
|
||||
$needs-prefixes: false;
|
||||
$webkit: ();
|
||||
$moz: ();
|
||||
$spec: ();
|
||||
|
||||
// Create lists for vendor-prefixed transform
|
||||
@each $list in $properties {
|
||||
@if nth($list, 1) == "transform" {
|
||||
$needs-prefixes: true;
|
||||
$list1: -webkit-transform;
|
||||
$list2: -moz-transform;
|
||||
$list3: ();
|
||||
|
||||
@each $var in $list {
|
||||
$list3: join($list3, $var);
|
||||
|
||||
@if $var != "transform" {
|
||||
$list1: join($list1, $var);
|
||||
$list2: join($list2, $var);
|
||||
}
|
||||
}
|
||||
|
||||
$webkit: append($webkit, $list1);
|
||||
$moz: append($moz, $list2);
|
||||
$spec: append($spec, $list3);
|
||||
} @else {
|
||||
$webkit: append($webkit, $list, comma);
|
||||
$moz: append($moz, $list, comma);
|
||||
$spec: append($spec, $list, comma);
|
||||
}
|
||||
}
|
||||
|
||||
@if $needs-prefixes {
|
||||
-webkit-transition: $webkit;
|
||||
-moz-transition: $moz;
|
||||
transition: $spec;
|
||||
} @else {
|
||||
@if length($properties) >= 1 {
|
||||
@include prefixer(transition, $properties, webkit moz spec);
|
||||
} @else {
|
||||
$properties: all 0.15s ease-out 0s;
|
||||
@include prefixer(transition, $properties, webkit moz spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin transition-property($properties...) {
|
||||
-webkit-transition-property: transition-property-names($properties, "webkit");
|
||||
-moz-transition-property: transition-property-names($properties, "moz");
|
||||
transition-property: transition-property-names($properties, false);
|
||||
}
|
||||
|
||||
@mixin transition-duration($times...) {
|
||||
@include prefixer(transition-duration, $times, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin transition-timing-function($motions...) {
|
||||
// ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier()
|
||||
@include prefixer(transition-timing-function, $motions, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin transition-delay($times...) {
|
||||
@include prefixer(transition-delay, $times, webkit moz spec);
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
@mixin user-select($value: none) {
|
||||
@include prefixer(user-select, $value, webkit moz ms spec);
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
@function assign-inputs($inputs, $pseudo: null) {
|
||||
$list: ();
|
||||
|
||||
@each $input in $inputs {
|
||||
$input: unquote($input);
|
||||
$input: if($pseudo, $input + ":" + $pseudo, $input);
|
||||
$list: append($list, $input, comma);
|
||||
}
|
||||
|
||||
@return $list;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Checks if a list does not contains a value.
|
||||
///
|
||||
/// @access private
|
||||
///
|
||||
/// @param {List} $list
|
||||
/// The list to check against.
|
||||
///
|
||||
/// @return {Bool}
|
||||
|
||||
@function contains-falsy($list) {
|
||||
@each $item in $list {
|
||||
@if not $item {
|
||||
@return true;
|
||||
}
|
||||
}
|
||||
|
||||
@return false;
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Checks if a list contains a value(s).
|
||||
///
|
||||
/// @access private
|
||||
///
|
||||
/// @param {List} $list
|
||||
/// The list to check against.
|
||||
///
|
||||
/// @param {List} $values
|
||||
/// A single value or list of values to check for.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// contains($list, $value)
|
||||
///
|
||||
/// @return {Bool}
|
||||
|
||||
@function contains($list, $values...) {
|
||||
@each $value in $values {
|
||||
@if type-of(index($list, $value)) != "number" {
|
||||
@return false;
|
||||
}
|
||||
}
|
||||
|
||||
@return true;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Checks for a valid CSS length.
|
||||
///
|
||||
/// @param {String} $value
|
||||
|
||||
@function is-length($value) {
|
||||
@return type-of($value) != "null" and (str-slice($value + "", 1, 4) == "calc"
|
||||
or index(auto inherit initial 0, $value)
|
||||
or (type-of($value) == "number" and not(unitless($value))));
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Programatically determines whether a color is light or dark.
|
||||
///
|
||||
/// @link http://robots.thoughtbot.com/closer-look-color-lightness
|
||||
///
|
||||
/// @param {Color (Hex)} $color
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// is-light($color)
|
||||
///
|
||||
/// @return {Bool}
|
||||
|
||||
@function is-light($hex-color) {
|
||||
$-local-red: red(rgba($hex-color, 1));
|
||||
$-local-green: green(rgba($hex-color, 1));
|
||||
$-local-blue: blue(rgba($hex-color, 1));
|
||||
$-local-lightness: ($-local-red * 0.2126 + $-local-green * 0.7152 + $-local-blue * 0.0722) / 255;
|
||||
|
||||
@return $-local-lightness > 0.6;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Checks for a valid number.
|
||||
///
|
||||
/// @param {Number} $value
|
||||
///
|
||||
/// @require {function} contains
|
||||
|
||||
@function is-number($value) {
|
||||
@return contains("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" 0 1 2 3 4 5 6 7 8 9, $value);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Checks for a valid CSS size.
|
||||
///
|
||||
/// @param {String} $value
|
||||
///
|
||||
/// @require {function} contains
|
||||
/// @require {function} is-length
|
||||
|
||||
@function is-size($value) {
|
||||
@return is-length($value)
|
||||
or contains("fill" "fit-content" "min-content" "max-content", $value);
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// Scaling Variables
|
||||
$golden: 1.618;
|
||||
$minor-second: 1.067;
|
||||
$major-second: 1.125;
|
||||
$minor-third: 1.2;
|
||||
$major-third: 1.25;
|
||||
$perfect-fourth: 1.333;
|
||||
$augmented-fourth: 1.414;
|
||||
$perfect-fifth: 1.5;
|
||||
$minor-sixth: 1.6;
|
||||
$major-sixth: 1.667;
|
||||
$minor-seventh: 1.778;
|
||||
$major-seventh: 1.875;
|
||||
$octave: 2;
|
||||
$major-tenth: 2.5;
|
||||
$major-eleventh: 2.667;
|
||||
$major-twelfth: 3;
|
||||
$double-octave: 4;
|
||||
|
||||
$modular-scale-ratio: $perfect-fourth !default;
|
||||
$modular-scale-base: em($em-base) !default;
|
||||
|
||||
@function modular-scale($increment, $value: $modular-scale-base, $ratio: $modular-scale-ratio) {
|
||||
$v1: nth($value, 1);
|
||||
$v2: nth($value, length($value));
|
||||
$value: $v1;
|
||||
|
||||
// scale $v2 to just above $v1
|
||||
@while $v2 > $v1 {
|
||||
$v2: ($v2 / $ratio); // will be off-by-1
|
||||
}
|
||||
@while $v2 < $v1 {
|
||||
$v2: ($v2 * $ratio); // will fix off-by-1
|
||||
}
|
||||
|
||||
// check AFTER scaling $v2 to prevent double-counting corner-case
|
||||
$double-stranded: $v2 > $v1;
|
||||
|
||||
@if $increment > 0 {
|
||||
@for $i from 1 through $increment {
|
||||
@if $double-stranded and ($v1 * $ratio) > $v2 {
|
||||
$value: $v2;
|
||||
$v2: ($v2 * $ratio);
|
||||
} @else {
|
||||
$v1: ($v1 * $ratio);
|
||||
$value: $v1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@if $increment < 0 {
|
||||
// adjust $v2 to just below $v1
|
||||
@if $double-stranded {
|
||||
$v2: ($v2 / $ratio);
|
||||
}
|
||||
|
||||
@for $i from $increment through -1 {
|
||||
@if $double-stranded and ($v1 / $ratio) < $v2 {
|
||||
$value: $v2;
|
||||
$v2: ($v2 / $ratio);
|
||||
} @else {
|
||||
$v1: ($v1 / $ratio);
|
||||
$value: $v1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@return $value;
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// Convert pixels to ems
|
||||
// eg. for a relational value of 12px write em(12) when the parent is 16px
|
||||
// if the parent is another value say 24px write em(12, 24)
|
||||
|
||||
@function em($pxval, $base: $em-base) {
|
||||
@if not unitless($pxval) {
|
||||
$pxval: strip-units($pxval);
|
||||
}
|
||||
@if not unitless($base) {
|
||||
$base: strip-units($base);
|
||||
}
|
||||
@return ($pxval / $base) * 1em;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// Convert pixels to rems
|
||||
// eg. for a relational value of 12px write rem(12)
|
||||
// Assumes $em-base is the font-size of <html>
|
||||
|
||||
@function rem($pxval) {
|
||||
@if not unitless($pxval) {
|
||||
$pxval: strip-units($pxval);
|
||||
}
|
||||
|
||||
$base: $em-base;
|
||||
@if not unitless($base) {
|
||||
$base: strip-units($base);
|
||||
}
|
||||
@return ($pxval / $base) * 1rem;
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Mixes a color with black.
|
||||
///
|
||||
/// @param {Color} $color
|
||||
///
|
||||
/// @param {Number (Percentage)} $percent
|
||||
/// The amount of black to be mixed in.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// background-color: shade(#ffbb52, 60%);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// background-color: #664a20;
|
||||
/// }
|
||||
///
|
||||
/// @return {Color}
|
||||
|
||||
@function shade($color, $percent) {
|
||||
@return mix(#000, $color, $percent);
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Strips the unit from a number.
|
||||
///
|
||||
/// @param {Number (With Unit)} $value
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// $dimension: strip-units(10em);
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// $dimension: 10;
|
||||
///
|
||||
/// @return {Number (Unitless)}
|
||||
|
||||
@function strip-units($value) {
|
||||
@return ($value / ($value * 0 + 1));
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Mixes a color with white.
|
||||
///
|
||||
/// @param {Color} $color
|
||||
///
|
||||
/// @param {Number (Percentage)} $percent
|
||||
/// The amount of white to be mixed in.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// background-color: tint(#6ecaa6, 40%);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// background-color: #a8dfc9;
|
||||
/// }
|
||||
///
|
||||
/// @return {Color}
|
||||
|
||||
@function tint($color, $percent) {
|
||||
@return mix(#fff, $color, $percent);
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// Return vendor-prefixed property names if appropriate
|
||||
// Example: transition-property-names((transform, color, background), moz) -> -moz-transform, color, background
|
||||
//************************************************************************//
|
||||
@function transition-property-names($props, $vendor: false) {
|
||||
$new-props: ();
|
||||
|
||||
@each $prop in $props {
|
||||
$new-props: append($new-props, transition-property-name($prop, $vendor), comma);
|
||||
}
|
||||
|
||||
@return $new-props;
|
||||
}
|
||||
|
||||
@function transition-property-name($prop, $vendor: false) {
|
||||
// put other properties that need to be prefixed here aswell
|
||||
@if $vendor and $prop == transform {
|
||||
@return unquote('-'+$vendor+'-'+$prop);
|
||||
}
|
||||
@else {
|
||||
@return $prop;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Converts shorthand to the 4-value syntax.
|
||||
///
|
||||
/// @param {List} $shorthand
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// margin: unpack(1em 2em);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// margin: 1em 2em 1em 2em;
|
||||
/// }
|
||||
|
||||
@function unpack($shorthand) {
|
||||
@if length($shorthand) == 1 {
|
||||
@return nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1);
|
||||
} @else if length($shorthand) == 2 {
|
||||
@return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 1) nth($shorthand, 2);
|
||||
} @else if length($shorthand) == 3 {
|
||||
@return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 3) nth($shorthand, 2);
|
||||
} @else {
|
||||
@return $shorthand;
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
//************************************************************************//
|
||||
// Helper function for str-to-num fn.
|
||||
// Source: http://sassmeister.com/gist/9647408
|
||||
//************************************************************************//
|
||||
@function _convert-units($number, $unit) {
|
||||
$strings: "px", "cm", "mm", "%", "ch", "pica", "in", "em", "rem", "pt", "pc", "ex", "vw", "vh", "vmin", "vmax", "deg", "rad", "grad", "turn";
|
||||
$units: 1px, 1cm, 1mm, 1%, 1ch, 1pica, 1in, 1em, 1rem, 1pt, 1pc, 1ex, 1vw, 1vh, 1vmin, 1vmax, 1deg, 1rad, 1grad, 1turn;
|
||||
$index: index($strings, $unit);
|
||||
|
||||
@if not $index {
|
||||
@warn "Unknown unit `#{$unit}`.";
|
||||
@return false;
|
||||
}
|
||||
|
||||
@if type-of($number) != "number" {
|
||||
@warn "`#{$number} is not a number`";
|
||||
@return false;
|
||||
}
|
||||
|
||||
@return $number * nth($units, $index);
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
/// Directional-property mixins are shorthands for writing properties like the following
|
||||
///
|
||||
/// @ignore You can also use `false` instead of `null`.
|
||||
///
|
||||
/// @param {List} $vals
|
||||
/// List of directional values
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include border-style(dotted null);
|
||||
/// @include margin(null 0 10px);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// border-bottom-style: dotted;
|
||||
/// border-top-style: dotted;
|
||||
/// margin-bottom: 10px;
|
||||
/// margin-left: 0;
|
||||
/// margin-right: 0;
|
||||
/// }
|
||||
///
|
||||
/// @require {function} contains-falsy
|
||||
///
|
||||
/// @return {List}
|
||||
|
||||
@function collapse-directionals($vals) {
|
||||
$output: null;
|
||||
|
||||
$a: nth($vals, 1);
|
||||
$b: if(length($vals) < 2, $a, nth($vals, 2));
|
||||
$c: if(length($vals) < 3, $a, nth($vals, 3));
|
||||
$d: if(length($vals) < 2, $a, nth($vals, if(length($vals) < 4, 2, 4)));
|
||||
|
||||
@if $a == 0 { $a: 0; }
|
||||
@if $b == 0 { $b: 0; }
|
||||
@if $c == 0 { $c: 0; }
|
||||
@if $d == 0 { $d: 0; }
|
||||
|
||||
@if $a == $b and $a == $c and $a == $d { $output: $a; }
|
||||
@else if $a == $c and $b == $d { $output: $a $b; }
|
||||
@else if $b == $d { $output: $a $b $c; }
|
||||
@else { $output: $a $b $c $d; }
|
||||
|
||||
@return $output;
|
||||
}
|
||||
|
||||
/// Output directional properties, for instance `margin`.
|
||||
///
|
||||
/// @access private
|
||||
///
|
||||
/// @param {String} $pre
|
||||
/// Prefix to use
|
||||
/// @param {String} $suf
|
||||
/// Suffix to use
|
||||
/// @param {List} $vals
|
||||
/// List of values
|
||||
///
|
||||
/// @require {function} collapse-directionals
|
||||
/// @require {function} contains-falsy
|
||||
|
||||
@mixin directional-property($pre, $suf, $vals) {
|
||||
// Property Names
|
||||
$top: $pre + "-top" + if($suf, "-#{$suf}", "");
|
||||
$bottom: $pre + "-bottom" + if($suf, "-#{$suf}", "");
|
||||
$left: $pre + "-left" + if($suf, "-#{$suf}", "");
|
||||
$right: $pre + "-right" + if($suf, "-#{$suf}", "");
|
||||
$all: $pre + if($suf, "-#{$suf}", "");
|
||||
|
||||
$vals: collapse-directionals($vals);
|
||||
|
||||
@if contains-falsy($vals) {
|
||||
@if nth($vals, 1) { #{$top}: nth($vals, 1); }
|
||||
|
||||
@if length($vals) == 1 {
|
||||
@if nth($vals, 1) { #{$right}: nth($vals, 1); }
|
||||
} @else {
|
||||
@if nth($vals, 2) { #{$right}: nth($vals, 2); }
|
||||
}
|
||||
|
||||
@if length($vals) == 2 {
|
||||
@if nth($vals, 1) { #{$bottom}: nth($vals, 1); }
|
||||
@if nth($vals, 2) { #{$left}: nth($vals, 2); }
|
||||
} @else if length($vals) == 3 {
|
||||
@if nth($vals, 3) { #{$bottom}: nth($vals, 3); }
|
||||
@if nth($vals, 2) { #{$left}: nth($vals, 2); }
|
||||
} @else if length($vals) == 4 {
|
||||
@if nth($vals, 3) { #{$bottom}: nth($vals, 3); }
|
||||
@if nth($vals, 4) { #{$left}: nth($vals, 4); }
|
||||
}
|
||||
} @else {
|
||||
#{$all}: $vals;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// Used for creating the source string for fonts using @font-face
|
||||
// Reference: http://goo.gl/Ru1bKP
|
||||
|
||||
@function font-url-prefixer($asset-pipeline) {
|
||||
@if $asset-pipeline == true {
|
||||
@return font-url;
|
||||
} @else {
|
||||
@return url;
|
||||
}
|
||||
}
|
||||
|
||||
@function font-source-declaration(
|
||||
$font-family,
|
||||
$file-path,
|
||||
$asset-pipeline,
|
||||
$file-formats,
|
||||
$font-url) {
|
||||
|
||||
$src: ();
|
||||
|
||||
$formats-map: (
|
||||
eot: "#{$file-path}.eot?#iefix" format("embedded-opentype"),
|
||||
woff2: "#{$file-path}.woff2" format("woff2"),
|
||||
woff: "#{$file-path}.woff" format("woff"),
|
||||
ttf: "#{$file-path}.ttf" format("truetype"),
|
||||
svg: "#{$file-path}.svg##{$font-family}" format("svg")
|
||||
);
|
||||
|
||||
@each $key, $values in $formats-map {
|
||||
@if contains($file-formats, $key) {
|
||||
$file-path: nth($values, 1);
|
||||
$font-format: nth($values, 2);
|
||||
|
||||
@if $asset-pipeline == true {
|
||||
$src: append($src, font-url($file-path) $font-format, comma);
|
||||
} @else {
|
||||
$src: append($src, url($file-path) $font-format, comma);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@return $src;
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
@function _gradient-positions-parser($gradient-type, $gradient-positions) {
|
||||
@if $gradient-positions
|
||||
and ($gradient-type == linear)
|
||||
and (type-of($gradient-positions) != color) {
|
||||
$gradient-positions: _linear-positions-parser($gradient-positions);
|
||||
}
|
||||
@else if $gradient-positions
|
||||
and ($gradient-type == radial)
|
||||
and (type-of($gradient-positions) != color) {
|
||||
$gradient-positions: _radial-positions-parser($gradient-positions);
|
||||
}
|
||||
@return $gradient-positions;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Private function for linear-gradient-parser
|
||||
@function _linear-angle-parser($image, $first-val, $prefix, $suffix) {
|
||||
$offset: null;
|
||||
$unit-short: str-slice($first-val, str-length($first-val) - 2, str-length($first-val));
|
||||
$unit-long: str-slice($first-val, str-length($first-val) - 3, str-length($first-val));
|
||||
|
||||
@if ($unit-long == "grad") or
|
||||
($unit-long == "turn") {
|
||||
$offset: if($unit-long == "grad", -100grad * 3, -0.75turn);
|
||||
}
|
||||
|
||||
@else if ($unit-short == "deg") or
|
||||
($unit-short == "rad") {
|
||||
$offset: if($unit-short == "deg", -90 * 3, 1.6rad);
|
||||
}
|
||||
|
||||
@if $offset {
|
||||
$num: _str-to-num($first-val);
|
||||
|
||||
@return (
|
||||
webkit-image: -webkit- + $prefix + ($offset - $num) + $suffix,
|
||||
spec-image: $image
|
||||
);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user