Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

refactor(switch): refactor for spec changes #882

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switches need interaction styles for mouse, keyboard, and touch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot about focus, thanks.

$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', onPanStart)
.on('$md.drag', onPan)
.on('$md.dragend', onPanEnd);

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

drag.width = thumbContainer.prop('offsetWidth');
element.removeClass('transition');
}
function onPan(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 onPanEnd(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();
});
}
}
};
}


}

})();
Loading