Instantly share code, notes, and snippets.
Created
July 10, 2012 08:32
-
Save ppcano/3082044 to your computer and use it in GitHub Desktop.
Flip Switch Button with Ember on Touch Environment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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