Adding switches.
parent
3eb10ba174
commit
d2439df4cf
|
@ -101,6 +101,11 @@
|
||||||
<iframe src="./styleguide/checkbox/demo.html" scrolling="no"></iframe>
|
<iframe src="./styleguide/checkbox/demo.html" scrolling="no"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="styleguide-demo">
|
||||||
|
<h1>Switch</h1>
|
||||||
|
<iframe src="./styleguide/switch/demo.html" scrolling="no"></iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="styleguide-demo">
|
<div class="styleguide-demo">
|
||||||
<h1>Slider</h1>
|
<h1>Slider</h1>
|
||||||
<iframe src="./styleguide/slider/demo.html" scrolling="no"></iframe>
|
<iframe src="./styleguide/slider/demo.html" scrolling="no"></iframe>
|
||||||
|
|
|
@ -83,6 +83,17 @@ $checkbox-color: nth($palette-primary, 6);
|
||||||
$checkbox-off-color: rgba(0, 0, 0, 0.54);
|
$checkbox-off-color: rgba(0, 0, 0, 0.54);
|
||||||
$checkbox-disabled-color: rgba(0, 0, 0, 0.26);
|
$checkbox-disabled-color: rgba(0, 0, 0, 0.26);
|
||||||
|
|
||||||
|
/* ========== Switches ========== */
|
||||||
|
|
||||||
|
$switch-color: nth($palette-primary, 6);
|
||||||
|
$switch-thumb-color: $switch-color;
|
||||||
|
$switch-track-color: rgba($switch-color, 0.5);
|
||||||
|
|
||||||
|
$switch-off-thumb-color: nth($palette-grey, 1);
|
||||||
|
$switch-off-track-color: rgba(0, 0, 0, 0.26);
|
||||||
|
$switch-disabled-thumb-color: nth($palette-grey, 5);
|
||||||
|
$switch-disabled-track-color: rgba(0, 0, 0, 0.12);
|
||||||
|
|
||||||
/* ========== Text fields ========== */
|
/* ========== Text fields ========== */
|
||||||
|
|
||||||
$input-text-background-color: transparent;
|
$input-text-background-color: transparent;
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
@import "../colors";
|
||||||
|
@import "../animation/animation";
|
||||||
|
@import "../shadow/shadow";
|
||||||
|
@import "../ripple/ripple";
|
||||||
|
|
||||||
|
$switch-label-height: 24px;
|
||||||
|
$switch-track-height: 14px;
|
||||||
|
$switch-track-length: 36px;
|
||||||
|
$switch-thumb-size: 20px;
|
||||||
|
$switch-track-top: ($switch-label-height - $switch-track-height) / 2;
|
||||||
|
$switch-thumb-top: ($switch-label-height - $switch-thumb-size) / 2;
|
||||||
|
$switch-ripple-size: $switch-label-height * 2;
|
||||||
|
|
||||||
|
.wsk-switch {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
height: $switch-label-height;
|
||||||
|
margin: 12px 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch__input {
|
||||||
|
line-height: $switch-label-height;
|
||||||
|
|
||||||
|
.wsk-switch.is-upgraded & {
|
||||||
|
// Hide input element, while still making it respond to focus.
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
opacity: 0;
|
||||||
|
-ms-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch__track {
|
||||||
|
background: $switch-off-track-color;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: $switch-track-top;
|
||||||
|
height: $switch-track-height;
|
||||||
|
width: $switch-track-length;
|
||||||
|
border-radius: $switch-track-height;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.wsk-switch.is-checked & {
|
||||||
|
background: $switch-track-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch.is-disabled & {
|
||||||
|
background: $switch-disabled-track-color;
|
||||||
|
cursor: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch__thumb {
|
||||||
|
background: $switch-off-thumb-color;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: $switch-thumb-top;
|
||||||
|
height: $switch-thumb-size;
|
||||||
|
width: $switch-thumb-size;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
@include shadow-z1();
|
||||||
|
|
||||||
|
@include material-animation-default(0.28s);
|
||||||
|
transition-property: left;
|
||||||
|
|
||||||
|
.wsk-switch.is-checked & {
|
||||||
|
background: $switch-thumb-color;
|
||||||
|
left: $switch-track-length - $switch-thumb-size;
|
||||||
|
|
||||||
|
@include shadow-z2();
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch.is-disabled & {
|
||||||
|
background: $switch-disabled-thumb-color;
|
||||||
|
cursor: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch__focus-helper {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
|
||||||
|
transform: translate(-$switch-button-size / 2, -$switch-button-size / 2);
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: $switch-button-size;
|
||||||
|
height: $switch-button-size;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
.wsk-switch.is-focused & {
|
||||||
|
box-shadow: 0 0 0px (($switch-ripple-size - $switch-button-size) / 2)
|
||||||
|
rgba(0, 0, 0, 0.1);
|
||||||
|
background-color: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch.is-focused.is-checked & {
|
||||||
|
box-shadow: 0 0 0px (($switch-ripple-size - $switch-button-size) / 2)
|
||||||
|
rgba($switch-color, 0.26);
|
||||||
|
background-color: rgba($switch-color, 0.26);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch__label {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: $switch-label-height;
|
||||||
|
margin: 0;
|
||||||
|
left: 24px;
|
||||||
|
|
||||||
|
.wsk-switch.is-disabled & {
|
||||||
|
color: $switch-disabled-thumb-color;
|
||||||
|
cursor: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch__ripple-container {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
top: -($switch-ripple-size - $switch-label-height) / 2;
|
||||||
|
left: $switch-thumb-size / 2 - $switch-ripple-size / 2;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: $switch-ripple-size;
|
||||||
|
height: $switch-ripple-size;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-mask-image: -webkit-radial-gradient(circle, white, black);
|
||||||
|
|
||||||
|
transition-duration: 0.40s;
|
||||||
|
transition-timing-function: step-end;
|
||||||
|
transition-property: left;
|
||||||
|
|
||||||
|
& .wsk-ripple {
|
||||||
|
background: $switch-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch.is-disabled & {
|
||||||
|
cursor: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch.is-disabled & .wsk-ripple {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsk-switch.is-checked & {
|
||||||
|
cursor: auto;
|
||||||
|
left: $switch-track-length - $switch-ripple-size / 2 -
|
||||||
|
$switch-thumb-size / 2;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Switch</title>
|
||||||
|
|
||||||
|
<link href='//fonts.googleapis.com/css?family=RobotoDraft:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en' rel='stylesheet' type='text/css'>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="demo.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="PreviewBlock">
|
||||||
|
|
||||||
|
<label class="wsk-switch wsk-js-switch wsk-js-ripple-effect" for="switch-1">
|
||||||
|
<input type="checkbox" id="switch-1" class="wsk-switch__input" />
|
||||||
|
<span class="wsk-switch__label">Switch me</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="wsk-switch wsk-js-switch wsk-js-ripple-effect" for="switch-2">
|
||||||
|
<input type="checkbox" id="switch-2" class="wsk-switch__input" />
|
||||||
|
<span class="wsk-switch__label">Flip me left and right</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="wsk-switch wsk-js-switch wsk-js-ripple-effect" for="switch-4">
|
||||||
|
<input type="checkbox" id="switch-4" class="wsk-switch__input" />
|
||||||
|
<span class="wsk-switch__label">Me too</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="wsk-switch wsk-js-switch wsk-js-ripple-effect" for="switch-5">
|
||||||
|
<input type="checkbox" id="switch-5" class="wsk-switch__input" disabled />
|
||||||
|
<span class="wsk-switch__label">Can't touch this</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- build:js(app/styleguide/checkbox/) ../../scripts/main.min.js -->
|
||||||
|
<script src="../wskComponentHandler.js"></script>
|
||||||
|
<script src="switch.js"></script>
|
||||||
|
<script src="../third_party/rAF.js"></script>
|
||||||
|
<script src="../ripple/ripple.js"></script>
|
||||||
|
<!-- endbuild -->
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,2 @@
|
||||||
|
@import "../styleguide_demo_bp";
|
||||||
|
@import "_switch";
|
|
@ -0,0 +1,220 @@
|
||||||
|
/**
|
||||||
|
* Class constructor for Checkbox WSK component.
|
||||||
|
* Implements WSK component design pattern defined at:
|
||||||
|
* https://github.com/jasonmayes/wsk-component-design-pattern
|
||||||
|
* @param {HTMLElement} element The element that will be upgraded.
|
||||||
|
*/
|
||||||
|
function MaterialSwitch(element) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
this.element_ = element;
|
||||||
|
|
||||||
|
// Initialize instance.
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store constants in one place so they can be updated easily.
|
||||||
|
* @enum {string | number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialSwitch.prototype.Constant_ = {
|
||||||
|
TINY_TIMEOUT: 0.001
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store strings for class names defined by this component that are used in
|
||||||
|
* JavaScript. This allows us to simply change it in one place should we
|
||||||
|
* decide to modify at a later date.
|
||||||
|
* @enum {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialSwitch.prototype.CssClasses_ = {
|
||||||
|
/**
|
||||||
|
* Class names should use camelCase and be prefixed with the word "material"
|
||||||
|
* to minimize conflict with 3rd party systems.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Upgrade classnames in HTML / CSS / JS to use material prefix to
|
||||||
|
// reduce conflict and convert to camelCase for consistency.
|
||||||
|
WSK_SWITCH_INPUT: 'wsk-switch__input',
|
||||||
|
|
||||||
|
WSK_SWITCH_TRACK: 'wsk-switch__track',
|
||||||
|
|
||||||
|
WSK_SWITCH_THUMB: 'wsk-switch__thumb',
|
||||||
|
|
||||||
|
WSK_SWITCH_FOCUS_HELPER: 'wsk-switch__focus-helper',
|
||||||
|
|
||||||
|
WSK_JS_RIPPLE_EFFECT: 'wsk-js-ripple-effect',
|
||||||
|
|
||||||
|
WSK_JS_RIPPLE_EFFECT_IGNORE_EVENTS: 'wsk-js-ripple-effect--ignore-events',
|
||||||
|
|
||||||
|
WSK_SWITCH_RIPPLE_CONTAINER: 'wsk-switch__ripple-container',
|
||||||
|
|
||||||
|
WSK_RIPPLE_CENTER: 'wsk-ripple--center',
|
||||||
|
|
||||||
|
WSK_RIPPLE: 'wsk-ripple',
|
||||||
|
|
||||||
|
IS_FOCUSED: 'is-focused',
|
||||||
|
|
||||||
|
IS_DISABLED: 'is-disabled',
|
||||||
|
|
||||||
|
IS_CHECKED: 'is-checked'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle change of state.
|
||||||
|
* @param {Event} event The event that fired.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialSwitch.prototype.onChange_ = function(event) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
this.updateClasses_(this.btnElement_, this.element_);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle focus of element.
|
||||||
|
* @param {Event} event The event that fired.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialSwitch.prototype.onFocus_ = function(event) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle lost focus of element.
|
||||||
|
* @param {Event} event The event that fired.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialSwitch.prototype.onBlur_ = function(event) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle mouseup.
|
||||||
|
* @param {Event} event The event that fired.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialSwitch.prototype.onMouseUp_ = function(event) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
this.blur_();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle class updates.
|
||||||
|
* @param {HTMLElement} button The button whose classes we should update.
|
||||||
|
* @param {HTMLElement} label The label whose classes we should update.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialSwitch.prototype.updateClasses_ = function(button, label) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (button.disabled) {
|
||||||
|
label.classList.add(this.CssClasses_.IS_DISABLED);
|
||||||
|
} else {
|
||||||
|
label.classList.remove(this.CssClasses_.IS_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button.checked) {
|
||||||
|
label.classList.add(this.CssClasses_.IS_CHECKED);
|
||||||
|
} else {
|
||||||
|
label.classList.remove(this.CssClasses_.IS_CHECKED);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add blur.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialSwitch.prototype.blur_ = function(event) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// TODO: figure out why there's a focus event being fired after our blur,
|
||||||
|
// so that we can avoid this hack.
|
||||||
|
window.setTimeout(function() {
|
||||||
|
this.btnElement_.blur();
|
||||||
|
}.bind(this), this.Constant_.TINY_TIMEOUT);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize element.
|
||||||
|
*/
|
||||||
|
MaterialSwitch.prototype.init = function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (this.element_) {
|
||||||
|
this.btnElement_ = this.element_.querySelector('.' +
|
||||||
|
this.CssClasses_.WSK_SWITCH_INPUT);
|
||||||
|
|
||||||
|
var track = document.createElement('div');
|
||||||
|
track.classList.add(this.CssClasses_.WSK_SWITCH_TRACK);
|
||||||
|
|
||||||
|
var thumb = document.createElement('div');
|
||||||
|
thumb.classList.add(this.CssClasses_.WSK_SWITCH_THUMB);
|
||||||
|
|
||||||
|
var focusHelper = document.createElement('span');
|
||||||
|
focusHelper.classList.add(this.CssClasses_.WSK_SWITCH_FOCUS_HELPER);
|
||||||
|
|
||||||
|
thumb.appendChild(focusHelper);
|
||||||
|
|
||||||
|
this.element_.appendChild(track);
|
||||||
|
this.element_.appendChild(thumb);
|
||||||
|
|
||||||
|
var rippleContainer;
|
||||||
|
if (this.element_.classList.contains(
|
||||||
|
this.CssClasses_.WSK_JS_RIPPLE_EFFECT)) {
|
||||||
|
this.element_.classList.add(
|
||||||
|
this.CssClasses_.WSK_JS_RIPPLE_EFFECT_IGNORE_EVENTS);
|
||||||
|
rippleContainer = document.createElement('span');
|
||||||
|
rippleContainer.classList.add(
|
||||||
|
this.CssClasses_.WSK_SWITCH_RIPPLE_CONTAINER);
|
||||||
|
rippleContainer.classList.add(this.CssClasses_.WSK_JS_RIPPLE_EFFECT);
|
||||||
|
rippleContainer.classList.add(this.CssClasses_.WSK_RIPPLE_CENTER);
|
||||||
|
|
||||||
|
var ripple = document.createElement('span');
|
||||||
|
ripple.classList.add(this.CssClasses_.WSK_RIPPLE);
|
||||||
|
|
||||||
|
rippleContainer.appendChild(ripple);
|
||||||
|
this.element_.appendChild(rippleContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.btnElement_.addEventListener('change', this.onChange_.bind(this));
|
||||||
|
|
||||||
|
this.btnElement_.addEventListener('focus', this.onFocus_.bind(this));
|
||||||
|
|
||||||
|
this.btnElement_.addEventListener('blur', this.onBlur_.bind(this));
|
||||||
|
|
||||||
|
this.element_.addEventListener('mouseup', this.onMouseUp_.bind(this));
|
||||||
|
|
||||||
|
rippleContainer.addEventListener('mouseup', this.onMouseUp_.bind(this));
|
||||||
|
|
||||||
|
this.updateClasses_(this.btnElement_, this.element_);
|
||||||
|
this.element_.classList.add('is-upgraded');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// On document ready, the component registers itself. It can assume
|
||||||
|
// componentHandler is available in the global scope.
|
||||||
|
componentHandler.register({
|
||||||
|
constructor: MaterialSwitch,
|
||||||
|
classAsString: 'MaterialSwitch',
|
||||||
|
cssClass: 'wsk-js-switch'
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue