Skip to content

Instantly share code, notes, and snippets.

@ppcano
Created July 10, 2012 08:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ppcano/3082044 to your computer and use it in GitHub Desktop.
Save ppcano/3082044 to your computer and use it in GitHub Desktop.
Flip Switch Button with Ember on Touch Environment
@white00:#fefefe;
@white01:#f9f9f9;
@white02:#fbfbfb;
@white03:#f0f0f0;
@white04:#efefef;
@grey00:#919191;
@grey01:#7d7d7d;
@grey02:#7f7f7f;
@grey03:#b6b6b6;
@grey04:#cdcdcd;
@grey05:#cfcfcf;
@blue00:#1b3b6f;
@blue01:#1654b5;
@blue02:#2a5bb3;
@blue03:#3672dc;
@blue04:#4085ec;
@blue05:#4d8fef;
@blue06:#76adfc;
@button-width:54px;
@button-height:27px;
@border-radius-size:3px;
@button-before-width: @button-width/4;
@button-after-width: @button-width - @button-before-width;
.logo-switch-button {
position: relative;
width: @button-width;
height: @button-height;
border-radius: @border-radius-size 0 0 @border-radius-size;
-webkit-transition: 1s all linear;
-webkit-appearance: none;
}
.logo-switch-button::after {
content: 'OFF';
position: absolute;
top: 0;
left: 0;
width: @button-after-width;
height: @button-height - 2px; // -2px because of border
border: 1px solid @grey00;
border-radius: @border-radius-size;
background: -webkit-linear-gradient(top, @grey04, @white02);
box-shadow: inset 0 1px 0 @white03;
-webkit-transition: 1s all linear;
// font style
text-align: center;
color: orange;
font: 700 14px sans-serif;
text-shadow: 0 -1px 0 @blue00;
line-height: 27px;
}
.logo-switch-button.is-on::after {
content: 'ON';
left: @button-before-width - 2px; // -2px because of border
}
.logo-switch-button::before {
content: '';
left: @button-after-width - 2px; // -2px because of border
position: absolute;
top: 0;
width: @button-before-width;
height: @button-height - 2px; // -2px because of border
border-radius: @border-radius-size;
border: 1px solid @grey01;
background: -webkit-linear-gradient(top, @grey05, @white04 50%, @white01 50%, @white00);
box-shadow: inset 0 2px 2px @grey03,
inset -3px 0 3px @grey03;
}
.logo-switch-button.is-on::before {
content: '';
left: 0;
border-color: @blue01;
background: -webkit-linear-gradient(top, @blue03, @blue04 50%, @blue05 50%, @blue06);
box-shadow: inset 0 2px 2px @blue02,
inset 3px 0 3px @blue02;
}
Yn.LogoSwitchButtonView = Em.View.extend({
classNames: ['logo-switch-button'],
classNameBindings: ['isOn'],
swipeOptions: {
direction: Em.OneGestureDirection.Left | Em.OneGestureDirection.Right,
cancelPeriod: 100,
swipeThreshold: 20,
initThreshold: 3
},
isOn: false,
swipeEnd: function(recognizer) {
var currentValue = this.get('isOn');
var direction = recognizer.swipeDirection;
if ( ( direction === Em.OneGestureDirection.Left && currentValue) ||
( direction === Em.OneGestureDirection.Right && !currentValue) ){
this.set('isOn', !currentValue);
}
}
});
@slider-height: 42px;
@slider-width: 80px;
.button_corner() {
// backgrounds extends into the padding, not the border.
-webkit-background-clip: padding-box;
-webkit-border-radius: @slider-height/2 ;
}
.switch-button {
overflow: visible;
position: relative;
height: @slider-height;
width: @slider-width;
.button_corner();
border: 1px solid #BBB;
background: #D6D6D6;
background-image: -webkit-linear-gradient(#D0D0D0, #DFDFDF);
> .sb-label-left {
z-index: 1;
left: 0;
border: 1px solid #2373A5;
background: #5393C5;
background-image: -webkit-linear-gradient(#5393C5 , #6FACD5);
}
> .sb-label-right {
z-index: 0;
right: 0;
border: 1px solid #BBB;
background: #D6D6D6;
background-image: -webkit-linear-gradient( #D0D0D0, #DFDFDF);
}
> .sb-label {
position: absolute;
min-height: 100%;
overflow: hidden;
border-width: 0;
.button_corner();
}
> .sb-inner {
margin: 0 @slider-height/2;
position: relative;
z-index: 1;
> .sb-inner-button {
position: absolute;
z-index: 1;
top: 50%;
width: @slider-height - 4px;
height: @slider-height - 4px;
margin-top: 1px;
margin-left: -1*(@slider-height/2 - 1px);
.button_corner();
border: 1px solid #CCC;
background: #EEE;
background-image: -webkit-linear-gradient( white , #F1F1F1);
-webkit-box-shadow: 0px 1px 4px rgba(0, 0, 0, .3);
}
}
}
Yn.SwitchButtonView = Em.ContainerView.extend({
classNames: ['switch-button'],
childViews: ['left','right','button'],
isOn: false,
left: Em.View.extend({
classNames: ['sb-label', 'sb-label-left']
}),
right: Em.View.extend({
classNames: ['sb-label', 'sb-label-right']
}),
button: Em.ContainerView.extend({
classNames: ['sb-inner'],
childViews: ['child'],
child: Em.View.extend({
classNames: ['sb-inner-button'],
percent:null,
// twoWayBinding
isOnBinding: 'parentView.parentView.isOn',
_leftChanged: Em.observer(function() {
var percent = this.get('percent');
if ( percent !== null && this.leftView) {
var handlePercent = this.width / this.switchButtonWidth * 100,
aPercent = percent && handlePercent + ( 100 - handlePercent ) * percent / 100,
bPercent = percent === 100 ? 0 : Math.min( handlePercent + 100 - aPercent, 100 );
this.$().css( "left", percent+"%");
this.leftView.$().css("width", aPercent+"%");
this.rightView.$().css("width", bPercent+"%");
}
}, 'percent' ),
_isOnChanged: Em.observer(function() {
var percent = this.get('isOn') ? 100 : 0;
this.set('percent', percent);
}, 'isOn' ),
panOptions: {
initThreshold: 10
},
didInsertElement: function(){
this._super();
this.switchButtonView = this.getPath('parentView.parentView');
this.switchButtonWidth = this.switchButtonView.$().width();
this.width = this.$().width();
this.leftView = this.switchButtonView.left;
this.rightView = this.switchButtonView.right;
this._isOnChanged();
},
panChange: function(recognizer) {
var changed = (100*recognizer.get('translation').x)/this.switchButtonWidth;
var percent = this.get('percent') + changed;
if ( percent > 100 ) {
percent = 100;
} else if ( percent < 0 ) {
percent = 0;
}
this.set('percent', percent);
},
panEnd: function(recognizer) {
this._panFinished(recognizer);
},
panCancel: function(recognizer) {
this._panFinished(recognizer);
},
_panFinished: function(recognizer) {
// on gesture finished, isOn property must be setup based on nearest value of percent property
var percent = ( this.get('percent') > 50 ) ? 100 : 0;
this.set('isOn', percent === 100 );
this.set('percent', percent);
}
})
})
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment