@@ -59,7 +59,7 @@ export class MdSlideToggle implements AfterContentInit, ControlValueAccessor {
59
59
private _hasFocus : boolean = false ;
60
60
private _isMousedown : boolean = false ;
61
61
private _isInitialized : boolean = false ;
62
- private _slideRenderer : MdSlideToggleRenderer = null ;
62
+ private _slideRenderer : SlideToggleRenderer = null ;
63
63
64
64
// State of the current drag, which holds required variables for the drag.
65
65
private _dragState : {
@@ -80,13 +80,12 @@ export class MdSlideToggle implements AfterContentInit, ControlValueAccessor {
80
80
// Returns the unique id for the visual hidden input.
81
81
getInputId = ( ) => `${ this . id || this . _uniqueId } -input` ;
82
82
83
- constructor ( private _elementRef : ElementRef ,
84
- private _renderer : Renderer ) {
85
- this . _slideRenderer = new MdSlideToggleRenderer ( this . _elementRef ) ;
86
- }
83
+ constructor ( private _elementRef : ElementRef , private _renderer : Renderer ) { }
87
84
88
85
/** TODO: internal */
89
86
ngAfterContentInit ( ) {
87
+ this . _slideRenderer = new SlideToggleRenderer ( this . _elementRef ) ;
88
+
90
89
// Mark this component as initialized in AfterContentInit because the initial checked value can
91
90
// possibly be set by NgModel or the checked attribute. This would cause the change event to
92
91
// be emitted, before the component is actually initialized.
@@ -105,7 +104,7 @@ export class MdSlideToggle implements AfterContentInit, ControlValueAccessor {
105
104
event . stopPropagation ( ) ;
106
105
107
106
// Once a drag is currently in progress, we do not want to toggle the slide-toggle on a click.
108
- if ( ! this . disabled && ! this . _dragState ) {
107
+ if ( ! this . disabled && ! this . _slideRenderer . isDragging ( ) ) {
109
108
this . toggle ( ) ;
110
109
}
111
110
}
@@ -223,89 +222,86 @@ export class MdSlideToggle implements AfterContentInit, ControlValueAccessor {
223
222
224
223
/** TODO: internal */
225
224
_onDragStart ( ) {
226
- if ( this . _dragState ) {
227
- return ;
228
- }
229
-
230
- let thumbBarRect = this . _slideRenderer . getThumbBarClientRect ( ) ;
231
- let thumbRect = this . _slideRenderer . getThumbClientRect ( ) ;
232
-
233
- this . _dragState = {
234
- barWidth : thumbBarRect . width - thumbRect . width
235
- } ;
236
-
237
- this . _slideRenderer . toggleDragging ( true ) ;
225
+ this . _slideRenderer . startThumbDrag ( this . checked ) ;
238
226
}
239
227
240
228
/** TODO: internal */
241
229
_onDrag ( event : HammerInput ) {
242
- if ( ! this . _dragState ) {
243
- return ;
244
- }
245
-
246
- let percentage = ( event . deltaX / this . _dragState . barWidth ) * 100 ;
247
-
248
- // When the slide-toggle was initially checked, then we have to start the drag at 100%
249
- if ( this . checked ) {
250
- percentage += 100 ;
251
- }
252
-
253
- percentage = Math . max ( 0 , Math . min ( percentage , 100 ) ) ;
254
-
255
- this . _slideRenderer . updateThumbPosition ( percentage ) ;
256
- this . _dragState . percentage = percentage ;
230
+ this . _slideRenderer . updateThumbPosition ( event . deltaX ) ;
257
231
}
258
232
259
233
/** TODO: internal */
260
234
_onDragEnd ( ) {
261
- if ( ! this . _dragState ) {
262
- return ;
263
- }
264
-
265
- this . checked = this . _dragState . percentage > 50 ;
266
-
267
- this . _slideRenderer . updateThumbPosition ( null ) ;
268
- this . _slideRenderer . toggleDragging ( false ) ;
269
-
270
- // We have to clear the drag after one tick, because otherwise
271
- // the click event will fire and toggle the slide-toggle again.
272
- setTimeout ( ( ) => { this . _dragState = null ; } , 0 ) ;
235
+ // Notice that we have to stop outside of the current event handler,
236
+ // because otherwise the click event will be fired and will reset the new checked variable.
237
+ setTimeout ( ( ) => {
238
+ this . checked = this . _slideRenderer . stopThumbDrag ( ) ;
239
+ } , 0 ) ;
273
240
}
274
241
275
242
}
276
243
277
244
/**
278
245
* Renderer for the Slide Toggle component, which separates DOM modification in it's own class
279
246
*/
280
- export class MdSlideToggleRenderer {
247
+ class SlideToggleRenderer {
281
248
282
- constructor ( private _elementRef : ElementRef ) { }
249
+ private _thumbEl : HTMLElement ;
250
+ private _thumbBarEl : HTMLElement ;
251
+ private _thumbBarWidth : number ;
252
+ private _checked : boolean ;
253
+ private _percentage : number ;
283
254
284
- getThumbClientRect ( ) : ClientRect {
285
- let thumbEl = this . _elementRef . nativeElement . querySelector ( '.md-slide-toggle-thumb-container' ) ;
286
- return thumbEl . getBoundingClientRect ( ) ;
255
+ constructor ( private _elementRef : ElementRef ) {
256
+ this . _thumbEl = _elementRef . nativeElement . querySelector ( '.md-slide-toggle-thumb-container' ) ;
257
+ this . _thumbBarEl = _elementRef . nativeElement . querySelector ( '.md-slide-toggle-bar' ) ;
287
258
}
288
259
289
- getThumbBarClientRect ( ) : ClientRect {
290
- let thumbBarEl = this . _elementRef . nativeElement . querySelector ( '.md-slide-toggle-bar' ) ;
291
- return thumbBarEl . getBoundingClientRect ( ) ;
260
+ /** Whether the slide-toggle is currently dragging. */
261
+ isDragging ( ) : boolean {
262
+ return ! ! this . _thumbBarWidth ;
292
263
}
293
264
294
- /**
295
- * Updates the thumb containers position by using the specified percentage.
296
- * When the percentage is set to `null`, the custom thumb position will be removed.
297
- */
298
- updateThumbPosition ( percentage : number ) {
299
- let thumbEl = this . _elementRef . nativeElement . querySelector ( '. md-slide-toggle-thumb-container ') ;
300
- applyCssTransform ( thumbEl , percentage === null ? '' : `translate3d( ${ percentage } %, 0, 0)` ) ;
265
+ /** Initializes the drag of the slide-toggle. */
266
+ startThumbDrag ( checked : boolean ) {
267
+ if ( ! this . _thumbBarWidth ) {
268
+ this . _thumbBarWidth = this . _thumbBarEl . clientWidth - this . _thumbEl . clientWidth ;
269
+ this . _checked = checked ;
270
+ this . _thumbEl . classList . add ( ' md-dragging ') ;
271
+ }
301
272
}
302
273
303
- /** Toggles the dragging class for the thumb container to toggle the transition duration. */
304
- toggleDragging ( isDragging : boolean ) {
305
- let thumbEl = this . _elementRef . nativeElement . querySelector ( '.md-slide-toggle-thumb-container' ) ;
306
- thumbEl . classList . toggle ( 'md-dragging' , isDragging ) ;
274
+ /** Stops the current drag and returns the new checked value. */
275
+ stopThumbDrag ( ) : boolean {
276
+ if ( this . _thumbBarWidth ) {
277
+ this . _thumbBarWidth = null ;
278
+ this . _thumbEl . classList . remove ( 'md-dragging' ) ;
279
+
280
+ applyCssTransform ( this . _thumbEl , '' ) ;
281
+
282
+ return this . _percentage > 50 ;
283
+ }
307
284
}
308
285
286
+ /** Updates the thumb containers position from the specified distance. */
287
+ updateThumbPosition ( distance : number ) {
288
+ if ( this . _thumbBarWidth ) {
289
+ this . _percentage = this . _getThumbPercentage ( distance ) ;
290
+ applyCssTransform ( this . _thumbEl , `translate3d(${ this . _percentage } %, 0, 0)` ) ;
291
+ }
292
+ }
293
+
294
+ /** Retrieves the percentage of thumb from the moved distance. */
295
+ private _getThumbPercentage ( distance : number ) {
296
+ let percentage = ( distance / this . _thumbBarWidth ) * 100 ;
297
+
298
+ // When the toggle was initially checked, then we have to start the drag at the end.
299
+ if ( this . _checked ) {
300
+ percentage += 100 ;
301
+ }
302
+
303
+ return Math . max ( 0 , Math . min ( percentage , 100 ) ) ;
304
+ }
309
305
310
306
}
311
307
0 commit comments