Skip to content
This repository has been archived by the owner on Aug 29, 2023. It is now read-only.

Commit

Permalink
refactor(switch): refactor to match new spec
Browse files Browse the repository at this point in the history
  • Loading branch information
ajoslin committed Dec 10, 2014
1 parent 4d39d7d commit 8bc9461
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 89 deletions.
19 changes: 7 additions & 12 deletions src/components/checkbox/checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ angular.module('material.components.checkbox', [
* </hljs>
*
*/
function MdCheckboxDirective(inputDirective, $mdInkRipple, $mdAria, $mdConstant, $mdTheming) {
function MdCheckboxDirective(inputDirective, $mdInkRipple, $mdAria, $mdConstant, $mdTheming, $mdUtil) {
inputDirective = inputDirective[0];

var CHECKED_CSS = 'md-checked';

return {
Expand All @@ -74,18 +73,10 @@ function MdCheckboxDirective(inputDirective, $mdInkRipple, $mdAria, $mdConstant,
tElement.attr('role', tAttrs.type);

return function postLink(scope, element, attr, ngModelCtrl) {
ngModelCtrl = ngModelCtrl || $mdUtil.fakeNgModel();
var checked = false;
$mdTheming(element);

// Create a mock ngModel if the user doesn't provide one
ngModelCtrl = ngModelCtrl || {
$setViewValue: function(value) {
this.$viewValue = value;
},
$parsers: [],
$formatters: []
};

$mdAria.expectWithText(tElement, 'aria-label');

// Reuse the original input[type=checkbox] directive from Angular core.
Expand All @@ -96,7 +87,11 @@ function MdCheckboxDirective(inputDirective, $mdInkRipple, $mdAria, $mdConstant,
0: {}
}, attr, [ngModelCtrl]);

element.on('click', listener);
// Used by switch. in Switch, we don't want click listeners; we have more granular
// touchup/touchdown listening.
if (!attr.mdNoClick) {
element.on('click', listener);
}
element.on('keypress', keypressHandler);
ngModelCtrl.$render = render;

Expand Down
6 changes: 2 additions & 4 deletions src/components/radioButton/radioButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ function mdRadioGroupDirective($mdUtil, $mdConstant, $mdTheming) {

function linkRadioGroup(scope, element, attr, ctrls) {
$mdTheming(element);
var rgCtrl = ctrls[0],
ngModelCtrl = ctrls[1] || {
$setViewValue: angular.noop
};
var rgCtrl = ctrls[0];
var ngModelCtrl = ctrls[1] || $mdUtil.fakeNgModel();

function keydownListener(ev) {
if (ev.keyCode === $mdConstant.KEY_CODE.LEFT_ARROW || ev.keyCode === $mdConstant.KEY_CODE.UP_ARROW) {
Expand Down
80 changes: 59 additions & 21 deletions src/components/switch/_switch.scss
Original file line number Diff line number Diff line change
@@ -1,42 +1,80 @@
$switch-width: $baseline-grid * 8;
$switch-width: 36px !default;
$switch-height: $baseline-grid * 3 !default;
$switch-bar-height: 14px !default;
$switch-thumb-size: 20px !default;

md-switch {
display: block;
position: relative;
height: $baseline-grid * 3;
margin: $baseline-grid;

display: flex;
align-items: center;

.md-switch-bar {
.md-container {
width: $switch-width;
height: $switch-height;
position: relative;
user-select: none;
margin-right: 8px;
}

.md-text {
border: 1px solid transparent;
}

.md-bar {
left: 1px;
width: $switch-width - 2px;
top: $switch-height / 2 - $switch-bar-height / 2;
height: $switch-bar-height;
border-radius: 8px;
position: absolute;
left: $baseline-grid * 2;
top: $baseline-grid * 1.5;
width: $baseline-grid * 4;
height: 1px;
pointer-events: none;
}

/* used also in _radio-button.scss */
.md-switch-thumb {
.md-thumb-container {
top: $switch-height / 2 - $switch-thumb-size / 2;
left: 0;
width: $switch-width - $switch-thumb-size;
position: absolute;
transform: translate3d(0,0,0);
z-index: 1;
}
&.md-checked .md-thumb-container {
transform: translate3d(100%,0,0);
}

.md-thumb {
position: absolute;
margin: 0;
left: 0;
top: 0;
outline: none;
height: $switch-thumb-size;
width: $switch-thumb-size;
border-radius: 50%;
box-shadow: $whiteframe-shadow-z1;

.md-container {
.md-ripple-container {
position: absolute;
transition: transform 0.2s linear;
transform: translate3d(0,0,0);
}
&.md-checked .md-container {
transform: translate3d($switch-width - 16,0,0);
display: block;
width: auto;
height: auto;
left: -$switch-thumb-size;
top: -$switch-thumb-size;
right: -$switch-thumb-size;
bottom: -$switch-thumb-size;
}
}

.md-label {
margin-left: $baseline-grid * 9;
&.transition {
.md-bar,
.md-thumb-container,
.md-thumb {
transition: $swift-ease-in-out;
transition-property: transform, background-color;
}
.md-bar,
.md-thumb {
transition-delay: 0.05s;
}
}

}
4 changes: 2 additions & 2 deletions src/components/switch/demoBasicUsage/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="inset">
<div class="inset" ng-controller="SwitchDemoCtrl">
<md-switch ng-model="data.cb1" aria-label="Switch 1">
Switch 1: {{ data.cb1 }}
</md-switch>
Expand All @@ -11,7 +11,7 @@
Switch (Disabled)
</md-switch>

<md-switch ng-disabled="true" aria-label="Disabled active switch" ng-model="data.cb4" ng-init="data.cb4=true">
<md-switch ng-disabled="true" aria-label="Disabled active switch" ng-model="data.cb4">
Switch (Disabled, Active)
</md-switch>

Expand Down
8 changes: 7 additions & 1 deletion src/components/switch/demoBasicUsage/script.js
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
angular.module('switchDemo1', ['ngMaterial']);
angular.module('switchDemo1', ['ngMaterial'])
.controller('SwitchDemoCtrl', function($scope) {
$scope.data = {
cb1: true,
cb4: true
};
});
47 changes: 40 additions & 7 deletions src/components/switch/switch-theme.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,46 @@
$switch-color: $foreground-secondary-color !default;
$switch-focus-color: map-get($foreground-color-palette, '1000');
$switch-color-palette: $primary-color-palette !default;
$switch-off-color-palette: $foreground-color-palette !default;

$switch-on-color: map-get($switch-color-palette, '500') !default;
$switch-on-bar-color: rgba($switch-on-color, 0.5) !default;

$switch-off-color: map-get($switch-off-color-palette, '50') !default;
$switch-off-bar-color: map-get($switch-off-color-palette, '500') !default;

$switch-disabled-color: map-get($switch-off-color-palette, '400') !default;
$switch-disabled-bar-color: rgba(#000, 0.12);

md-switch.md-#{$theme-name}-theme {
.md-switch-bar {
background-color: $switch-color;
.md-thumb {
background-color: $switch-off-color;
}
.md-bar {
background-color: $switch-off-bar-color;
}

&.md-checked {
.md-thumb {
background-color: $switch-on-color;
}
.md-bar {
background-color: $switch-on-bar-color;
}
}
.md-switch-thumb {
&:focus .md-label {
border: 1px dotted black;

&[disabled] {
.md-thumb {
background-color: $switch-disabled-color;
}
.md-bar {
background-color: $switch-disabled-bar-color;
}
}

&:focus {
.md-text {
border-color: black;
border-style: dotted;
}
}

}
83 changes: 71 additions & 12 deletions src/components/switch/switch.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@

angular.module('material.components.switch', [
'material.core',
'material.components.checkbox',
'material.components.radioButton'
'material.components.checkbox'
])
.directive('mdSwitch', MdSwitch);

Expand Down Expand Up @@ -47,30 +46,90 @@ angular.module('material.components.switch', [
*
* </hljs>
*/
function MdSwitch(mdCheckboxDirective, mdRadioButtonDirective, $mdTheming) {
function MdSwitch(mdCheckboxDirective, $mdTheming, $mdUtil, $document, $mdConstant, $parse, $$rAF) {
var checkboxDirective = mdCheckboxDirective[0];
var radioButtonDirective = mdRadioButtonDirective[0];

return {
restrict: 'E',
transclude: true,
template:
'<div class="md-switch-bar"></div>' +
'<div class="md-switch-thumb">' +
radioButtonDirective.template +
'<div class="md-container">' +
'<div class="md-bar"></div>' +
'<div class="md-thumb-container">' +
'<div class="md-thumb" md-ink-ripple md-ink-ripple-checkbox></div>' +
'</div>'+
'</div>' +
'<div ng-transclude class="md-text">' +
'</div>',
require: '?ngModel',
compile: compile
};

function compile(element, attr) {
var thumb = angular.element(element[0].querySelector('.md-switch-thumb'));
var checkboxLink = checkboxDirective.compile(thumb, attr);
var checkboxLink = checkboxDirective.compile(element, attr);

return function (scope, element, attr, ngModelCtrl) {
$mdTheming(element);
return checkboxLink(scope, thumb, attr, ngModelCtrl);
return function (scope, element, attr, ngModel) {
ngModel = ngModel || $mdUtil.fakeNgModel();
var disabledGetter = $parse(attr.ngDisabled);
var thumbContainer = angular.element(element[0].querySelector('.md-thumb-container'));
var switchContainer = angular.element(element[0].querySelector('.md-container'));

// no transition on initial load
$$rAF(function() {
element.addClass('transition');
});

// Tell the checkbox we don't want a click listener.
// Our drag listener tells us everything, using more granular events.
attr.mdNoClick = true;
checkboxLink(scope, element, attr, ngModel);

$mdUtil.attachDragBehavior(scope, switchContainer);

// These events are triggered by setup drag
switchContainer.on('$md.dragstart', onDragStart)
.on('$md.drag', onDrag)
.on('$md.dragend', onDragEnd);

function onDragStart(ev, drag) {
// Don't go if ng-disabled===true
if (disabledGetter(scope)) return ev.preventDefault();

drag.width = thumbContainer.prop('offsetWidth');
element.removeClass('transition');
}
function onDrag(ev, drag) {
var percent = drag.distance / drag.width;

//if checked, start from right. else, start from left
var translate = ngModel.$viewValue ? 1 - percent : -percent;
// Make sure the switch stays inside its bounds, 0-1%
translate = Math.max(0, Math.min(1, translate));

thumbContainer.css($mdConstant.CSS.TRANSFORM, 'translate3d(' + (100*translate) + '%,0,0)');
drag.translate = translate;
}
function onDragEnd(ev, drag) {
if (disabledGetter(scope)) return false;

element.addClass('transition');
thumbContainer.css($mdConstant.CSS.TRANSFORM, '');

// We changed if there is no distance (this is a click a click),
// or if the drag distance is >50% of the total.
var isChanged = Math.abs(drag.distance || 0) < 5 ||
(ngModel.$viewValue ? drag.translate < 0.5 : drag.translate > 0.5);
if (isChanged) {
scope.$apply(function() {
ngModel.$setViewValue(!ngModel.$viewValue);
ngModel.$render();
});
}
}
};
}


}

})();

0 comments on commit 8bc9461

Please sign in to comment.