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

Commit

Permalink
feat(material-switch): add switch component
Browse files Browse the repository at this point in the history
Closes #80
  • Loading branch information
ajoslin committed Aug 28, 2014
1 parent 642ee4e commit 4975c74
Show file tree
Hide file tree
Showing 14 changed files with 146 additions and 7 deletions.
1 change: 1 addition & 0 deletions config/build.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ module.exports = {
'src/components/radioButton/radioButton.js',
'src/components/sidenav/sidenav.js',
'src/components/slider/slider.js',
'src/components/switch/switch.js',
'src/components/tabs/tabs.js',
'src/components/tabs/util/*.js',
'src/components/toast/toast.js',
Expand Down
1 change: 0 additions & 1 deletion src/base/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ var Util = {

/**
* Converts snake_case to camelCase.
* Also there is special case for Moz prefix starting with upper case letter.
* @param name Name to normalize
*/
camelCase: function camelCase(name) {
Expand Down
2 changes: 0 additions & 2 deletions src/components/animate/_effects.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ material-ink-bar {
margin-top: -2px;
}



canvas.material-ink-ripple {
pointer-events: none;
position: absolute;
Expand Down
4 changes: 2 additions & 2 deletions src/components/checkbox/checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function materialCheckboxDirective(inputDirectives, $expectAria) {
require: '?ngModel',
template:
'<div class="material-container">' +
'<material-ripple start="center" class="circle" material-checked="{{ checked }}" ></material-ripple>' +
'<material-ripple start="center" class="circle"></material-ripple>' +
'<div class="material-icon"></div>' +
'</div>' +
'<div ng-transclude class="material-label"></div>',
Expand Down Expand Up @@ -109,7 +109,7 @@ function materialCheckboxDirective(inputDirectives, $expectAria) {
}
}
function listener(ev) {
if ( Util.isDisabled(element) ) return;
if (element[0].hasAttribute('disabled')) return;

scope.$apply(function() {
checked = !checked;
Expand Down
3 changes: 2 additions & 1 deletion src/components/radioButton/_radio-button.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

material-radio-button {
material-radio-button,
.material-switch-thumb { // Used in switch
display: block;
margin: 15px;
white-space: nowrap;
Expand Down
2 changes: 1 addition & 1 deletion src/components/radioButton/radioButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ function materialRadioButtonDirective($expectAria) {
$expectAria(element, Constant.ARIA.PROPERTY.LABEL, element.text());

function listener(ev) {
if ( Util.isDisabled(element) ) return;
if (element[0].hasAttribute('disabled')) return;

scope.$apply(function() {
rgCtrl.setViewValue(attr.value, ev && ev.type);
Expand Down
32 changes: 32 additions & 0 deletions src/components/switch/_switch.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
material-switch {
position: relative;
width: $switch-width;
height: $baseline-grid * 3;

@include flex-display();
@include flex-justify-content(center);
@include flex-align-items(center);

.material-switch-bar {
width: 32px;
height: 1px;
background-color: #5a5a5a;
pointer-events: none;
}

/* check _radio-button.scss */
.material-switch-thumb {
position: absolute;
margin: 0;
left: 0;
top: 0;

-webkit-transition: -webkit-transform 0.2s linear;
transition: transform 0.2s linear;
@include transform-translate3d(0,0,0);

&.material-checked {
@include transform-translate3d($switch-width - 16,0,0);
}
}
}
5 changes: 5 additions & 0 deletions src/components/switch/demo1/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div ng-app="myApp">
<material-switch ng-model="val"></material-switch>
<br/>
Value: {{val}}
</div>
1 change: 1 addition & 0 deletions src/components/switch/demo1/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
angular.module('myApp', ['ngMaterial']);
10 changes: 10 additions & 0 deletions src/components/switch/module.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"module": "material.components.switch",
"name": "Switch",
"demos": {
"demo1": {
"name": "Switch Basic Usage",
"files": ["demo1/*"]
}
}
}
39 changes: 39 additions & 0 deletions src/components/switch/switch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
angular.module('material.components.switch', [
'material.components.checkbox',
'material.components.radioButton',
])

.directive('materialSwitch', [
'materialCheckboxDirective',
'materialRadioButtonDirective',
MaterialSwitch
]);

function MaterialSwitch(checkboxDirectives, radioButtonDirectives) {
var checkboxDirective = checkboxDirectives[0];
var radioButtonDirective = radioButtonDirectives[0];

return {
restrict: 'E',
transclude: true,
template:
'<div class="material-switch-bar"></div>' +
'<div class="material-switch-thumb">' +
radioButtonDirective.template +
'</div>',
require: '?ngModel',
compile: compile
};

function compile(element, attr) {

var thumb = angular.element(element[0].querySelector('.material-switch-thumb'));
//Copy down disabled attributes for checkboxDirective to use
thumb.attr('disabled', attr.disabled);
thumb.attr('ngDisabled', attr.ngDisabled);

return function postLink(scope, element, attr, ngModelCtrl) {
checkboxDirective.link(scope, thumb, attr, ngModelCtrl);
};
}
}
47 changes: 47 additions & 0 deletions src/components/switch/switch.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
describe('<material-switch>', function() {
var CHECKED_CSS = 'material-checked';

beforeEach(module('material.components.switch'));

it('should set checked css class and aria-checked attributes', inject(function($compile, $rootScope) {
var element = $compile('<div>' +
'<material-switch ng-model="blue">' +
'</material-switch>' +
'<material-switch ng-model="green">' +
'</material-switch>' +
'</div>')($rootScope);

$rootScope.$apply(function(){
$rootScope.blue = false;
$rootScope.green = true;
});

var cbElements = element.find('.material-switch-thumb');

expect(cbElements.eq(0).hasClass(CHECKED_CSS)).toEqual(false);
expect(cbElements.eq(1).hasClass(CHECKED_CSS)).toEqual(true);
expect(cbElements.eq(0).attr('aria-checked')).toEqual('false');
expect(cbElements.eq(1).attr('aria-checked')).toEqual('true');
expect(cbElements.eq(0).attr('role')).toEqual('checkbox');
}));

it('should be disabled with disabled attr', inject(function($compile, $rootScope) {
var element = $compile('<div>' +
'<material-switch disabled ng-model="blue">' +
'</material-switch>' +
'</div>')($rootScope);

var switchThumb = element.find('.material-switch-thumb');

$rootScope.$apply('blue = false');

switchThumb.triggerHandler('click');
expect($rootScope.blue).toBe(false);

switchThumb.removeAttr('disabled');

switchThumb.triggerHandler('click');
expect($rootScope.blue).toBe(true);
}));

});
1 change: 1 addition & 0 deletions src/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"components/sidenav/sidenav",
"components/form/form",
"components/slider/slider",
"components/switch/switch",
"components/toast/toast",
"components/toolbar/toolbar",
"components/tabs/tabs",
Expand Down
5 changes: 5 additions & 0 deletions src/theme/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ $slider-track-height: 2px;
$slider-thumb-width: 10px;
$slider-thumb-height: $slider-thumb-width;

// Switch
//--------------------------------------------

$switch-width: $baseline-grid * 8;


// Checkbox
//--------------------------------------------
Expand Down

0 comments on commit 4975c74

Please sign in to comment.