1- /* eslint-disable ember/no-classic-components, ember/no-component-lifecycle-hooks, ember/no-get, ember/no-mixins, ember/require-tagless-components, no-unused-vars */
1+ /* global Hammer */
22/**
33 * @module ember-paper
44 */
5- import { inject as service } from '@ember/service' ;
6-
7- import Component from '@ember/component' ;
5+ import Focusable from './-focusable' ;
6+ import { tracked } from '@glimmer/tracking' ;
87import { assert } from '@ember/debug' ;
9- import { get , computed } from '@ember/object' ;
10- import { bind } from '@ember/runloop ' ;
8+ import { action } from '@ember/object' ;
9+ import { inject as service } from '@ember/service ' ;
1110import { htmlSafe } from '@ember/template' ;
12- import FocusableMixin from 'ember-paper/mixins/focusable-mixin' ;
13- import ProxiableMixin from 'ember-paper/mixins/proxiable-mixin' ;
14- import { invokeAction } from 'ember-paper/utils/invoke-action' ;
15-
16- /* global Hammer */
1711
1812/**
1913 * @class PaperSwitch
20- * @extends Ember.Component
21- * @uses FocusableMixin
22- * @uses ProxiableMixin
14+ * @extends Component
2315 */
24- export default Component . extend ( FocusableMixin , ProxiableMixin , {
25- tagName : 'md-switch' ,
26- classNames : [ 'paper-switch' , 'md-default-theme' ] ,
27- classNameBindings : [
28- 'value:md-checked' ,
29- 'dragging:md-dragging' ,
30- 'warn:md-warn' ,
31- 'accent:md-accent' ,
32- 'primary:md-primary' ,
33- ] ,
34- toggle : true ,
35- constants : service ( ) ,
36- value : false ,
37- disabled : false ,
38- dragging : false ,
39-
40- thumbContainerStyle : computed ( 'dragging' , 'dragAmount' , function ( ) {
41- if ( ! this . dragging ) {
42- return htmlSafe ( '' ) ;
16+ export default class PaperSwitch extends Focusable {
17+ @service constants ;
18+
19+ /**
20+ * Reference to the component's DOM element
21+ * @type {HTMLElement }
22+ */
23+ element ;
24+ /**
25+ * The parent this component is bound to.
26+ * @type {PaperRadioGroup|PaperForm|PaperItem|PaperTabs }
27+ */
28+ parent ;
29+ /**
30+ * Marks whether the component should register itself to the supplied parent
31+ * @type {Boolean }
32+ */
33+ shouldRegister ;
34+ /**
35+ * Marks whether the component should skip being proxied.
36+ * @type {Boolean }
37+ */
38+ skipProxy ;
39+
40+ /* Focusable Overrides */
41+ toggle = true ;
42+
43+ /**
44+ * specifies the positive amount the switch has been dragged.
45+ * @type {number|null }
46+ */
47+ @tracked dragAmount = null ;
48+ /**
49+ * specifies whether the switch is currently being dragged.
50+ * @type {boolean }
51+ */
52+ @tracked dragging = false ;
53+ /**
54+ * specifies the width of the switch to calculate drag deltas.
55+ * @type {number }
56+ */
57+ @tracked switchWidth = 0 ;
58+
59+ // Lifecycle hooks
60+ constructor ( owner , args ) {
61+ super ( owner , args ) ;
62+
63+ this . shouldRegister = this . args . shouldRegister || false ;
64+ this . skipProxy = this . args . skipProxy || false ;
65+ this . toggle = this . args . toggle || false ;
66+
67+ if ( this . shouldRegister ) {
68+ assert (
69+ 'A parent component should be supplied to <PaperSwitch> when shouldRegister=true' ,
70+ this . args . parentComponent
71+ ) ;
72+ this . parent = this . args . parentComponent ;
4373 }
4474
45- let translate = Math . max ( 0 , Math . min ( 100 , this . dragAmount * 100 ) ) ;
46- let transformProp = `translate3d(${ translate } %, 0, 0)` ;
47- return htmlSafe (
48- `transform: ${ transformProp } ;-webkit-transform: ${ transformProp } `
75+ assert (
76+ '<PaperSwitch> requires an `onChange` action or null for no action.' ,
77+ this . args . onChange !== undefined
4978 ) ;
50- } ) ,
51-
52- didInsertElement ( ) {
53- this . _super ( ...arguments ) ;
79+ }
80+
81+ /**
82+ * Performs any required DOM setup.
83+ * @param element
84+ */
85+ @action didInsertNode ( element ) {
86+ this . element = element ;
87+ this . registerListeners ( element ) ;
88+
89+ if ( this . shouldRegister ) {
90+ this . parent . registerChild ( this ) ;
91+ }
5492
5593 // Only setup if the switch is not disabled
5694 if ( ! this . disabled ) {
5795 this . _setupSwitch ( ) ;
5896 }
59- } ,
60-
61- init ( ) {
62- this . _super ( ...arguments ) ;
63- assert (
64- '{{paper-switch}} requires an `onChange` action or null for no action.' ,
65- this . onChange !== undefined
66- ) ;
67- } ,
68-
69- willDestroyElement ( ) {
70- this . _super ( ...arguments ) ;
71- this . _teardownSwitch ( ) ;
72- } ,
73-
74- didUpdateAttrs ( ) {
75- this . _super ( ...arguments ) ;
97+ }
7698
99+ @action didUpdateNode ( ) {
77100 if ( ! this . disabled && ! this . _switchContainerHammer ) {
78101 this . _setupSwitch ( ) ;
79102 } else if ( ! this . disabled && this . _switchContainerHammer ) {
80103 this . _switchContainerHammer . set ( { enable : true } ) ;
81104 } else if ( this . disabled && this . _switchContainerHammer ) {
82105 this . _switchContainerHammer . set ( { enable : false } ) ;
83106 }
84- } ,
107+ }
108+
109+ /**
110+ * Performs any required DOM teardown.
111+ * @param element
112+ */
113+ @action willDestroyNode ( element ) {
114+ this . unregisterListeners ( element ) ;
115+ this . _teardownSwitch ( ) ;
116+ }
85117
86- _setupSwitch ( ) {
87- this . set (
88- 'switchWidth' ,
89- this . element . querySelector ( '.md-thumb-container' ) . offsetWidth
118+ willDestroy ( ) {
119+ super . willDestroy ( ...arguments ) ;
120+
121+ if ( this . shouldRegister ) {
122+ this . parent . unregisterChild ( this ) ;
123+ }
124+ }
125+
126+ /**
127+ * specifies the current switch value.
128+ * @type {boolean }
129+ */
130+ get value ( ) {
131+ return this . args . value ;
132+ }
133+
134+ /**
135+ * Calculates and returns a css animation transform for the switch's thumb.
136+ * @returns {string }
137+ */
138+ get thumbContainerStyle ( ) {
139+ if ( ! this . dragging ) {
140+ return htmlSafe ( '' ) ;
141+ }
142+
143+ let translate = Math . max ( 0 , Math . min ( 100 , this . dragAmount * 100 ) ) ;
144+ let transformProp = `translate3d(${ translate } %, 0, 0)` ;
145+ return htmlSafe (
146+ `transform: ${ transformProp } ;-webkit-transform: ${ transformProp } `
90147 ) ;
148+ }
149+
150+ _setupSwitch ( ) {
151+ this . switchWidth = this . element . querySelector (
152+ '.md-thumb-container'
153+ ) . offsetWidth ;
91154
92155 let switchContainer = this . element . querySelector ( '.md-container' ) ;
93156 let switchHammer = new Hammer ( switchContainer ) ;
@@ -96,20 +159,20 @@ export default Component.extend(FocusableMixin, ProxiableMixin, {
96159 // Enable dragging the switch container
97160 switchHammer . get ( 'pan' ) . set ( { threshold : 1 } ) ;
98161 switchHammer
99- . on ( 'panstart' , bind ( this , this . _dragStart ) )
100- . on ( 'panmove' , bind ( this , this . _drag ) )
101- . on ( 'panend' , bind ( this , this . _dragEnd ) ) ;
162+ . on ( 'panstart' , this . _dragStart . bind ( this ) )
163+ . on ( 'panmove' , this . _drag . bind ( this ) )
164+ . on ( 'panend' , this . _dragEnd . bind ( this ) ) ;
102165
103166 // Enable tapping gesture on the switch
104167 this . _switchHammer = new Hammer ( this . element ) ;
105- this . _switchHammer . on ( 'tap' , bind ( this , this . _dragEnd ) ) ;
168+ this . _switchHammer . on ( 'tap' , this . _dragEnd . bind ( this ) ) ;
106169
107- this . _onClickHandleNativeClick = bind ( this , this . _handleNativeClick ) ;
170+ this . _onClickHandleNativeClick = this . _handleNativeClick . bind ( this ) ;
108171
109172 this . element
110173 . querySelector ( '.md-container' )
111174 . addEventListener ( 'click' , this . _onClickHandleNativeClick ) ;
112- } ,
175+ }
113176
114177 _handleNativeClick ( ev ) {
115178 let bubbles = this . bubbles ;
@@ -119,7 +182,7 @@ export default Component.extend(FocusableMixin, ProxiableMixin, {
119182 }
120183
121184 return bubbles ;
122- } ,
185+ }
123186
124187 _teardownSwitch ( ) {
125188 if ( this . _switchContainerHammer ) {
@@ -130,19 +193,19 @@ export default Component.extend(FocusableMixin, ProxiableMixin, {
130193 . querySelector ( '.md-container' )
131194 . removeEventListener ( 'click' , this . _onClickHandleNativeClick ) ;
132195 this . _onClickHandleNativeClick = null ;
133- } ,
196+ }
134197
135198 _dragStart ( ) {
136- this . set ( ' dragAmount' , + this . value ) ;
137- this . set ( ' dragging' , true ) ;
138- } ,
199+ this . dragAmount = + this . value ;
200+ this . dragging = true ;
201+ }
139202
140203 _drag ( event ) {
141204 if ( ! this . disabled ) {
142205 // Set the amount the switch has been dragged
143- this . set ( ' dragAmount' , + this . value + event . deltaX / this . switchWidth ) ;
206+ this . dragAmount = + this . value + event . deltaX / this . switchWidth ;
144207 }
145- } ,
208+ }
146209
147210 _dragEnd ( ) {
148211 if ( ! this . disabled ) {
@@ -154,31 +217,35 @@ export default Component.extend(FocusableMixin, ProxiableMixin, {
154217 ( value && dragAmount < 0.5 ) ||
155218 ( ! value && dragAmount > 0.5 )
156219 ) {
157- invokeAction ( this , 'onChange' , ! value ) ;
220+ if ( this . args . onChange ) {
221+ this . args . onChange ( ! value ) ;
222+ }
158223 }
159- this . set ( ' dragging' , false ) ;
160- this . set ( ' dragAmount' , null ) ;
224+ this . dragging = false ;
225+ this . dragAmount = null ;
161226 }
162- } ,
227+ }
163228
164- focusIn ( ) {
229+ @ action handleFocusIn ( ) {
165230 // Focusing in w/o being pressed should use the default behavior
166231 if ( ! this . pressed ) {
167- this . _super ( ...arguments ) ;
232+ super . handleFocusIn ( ...arguments ) ;
168233 }
169- } ,
234+ }
170235
171- keyPress ( ev ) {
236+ @ action handleKeyPress ( ev ) {
172237 if (
173- ev . which === this . get ( ' constants.KEYCODE.SPACE' ) ||
174- ev . which === this . get ( ' constants.KEYCODE.ENTER' )
238+ ev . which === this . constants . KEYCODE . SPACE ||
239+ ev . which === this . constants . KEYCODE . ENTER
175240 ) {
176241 ev . preventDefault ( ) ;
177242 this . _dragEnd ( ) ;
178243 }
179- } ,
244+ }
180245
181246 processProxy ( ) {
182- invokeAction ( this , 'onChange' , ! this . value ) ;
183- } ,
184- } ) ;
247+ if ( this . args . onChange ) {
248+ this . args . onChange ( ! this . value ) ;
249+ }
250+ }
251+ }
0 commit comments