21
21
* THE SOFTWARE.
22
22
*/
23
23
24
- const registry = Object . create ( null ) ;
24
+ // tslint:disable:only-arrow-functions
25
25
26
- const CONSOLE_WARN = console . warn . bind ( console ) ;
26
+ import { MDCComponent , MDCFoundation } from '@material/base/index' ;
27
27
28
- function _emit ( evtType , evtData , shouldBubble = false ) {
28
+ interface ComponentClass {
29
+ // tslint:disable-next-line:no-any a component can pass in anything it needs to the constructor
30
+ new < F extends MDCFoundation > ( root : Element , foundation ?: F , ...args : any [ ] ) : MDCComponent < F > ;
31
+ attachTo < F extends MDCFoundation > ( root : Element ) : MDCComponent < F > ;
32
+ }
33
+
34
+ interface Registry {
35
+ [ key : string ] : ComponentClass ;
36
+ }
37
+
38
+ const registry : Registry = { } ;
39
+
40
+ const CONSOLE_WARN = console . warn . bind ( console ) ; // tslint:disable-line:no-console
41
+
42
+ function _emit < T extends object > ( evtType : string , evtData : T , shouldBubble = false ) {
29
43
let evt ;
30
44
if ( typeof CustomEvent === 'function' ) {
31
- evt = new CustomEvent ( evtType , {
32
- detail : evtData ,
45
+ evt = new CustomEvent < T > ( evtType , {
33
46
bubbles : shouldBubble ,
47
+ detail : evtData ,
34
48
} ) ;
35
49
} else {
36
50
evt = document . createEvent ( 'CustomEvent' ) ;
@@ -40,36 +54,39 @@ function _emit(evtType, evtData, shouldBubble = false) {
40
54
document . dispatchEvent ( evt ) ;
41
55
}
42
56
57
+ /* istanbul ignore next: optional argument is not a branch statement */
43
58
/**
44
- * Auto-initializes all mdc components on a page.
59
+ * Auto-initializes all MDC components on a page.
45
60
*/
46
- export default function mdcAutoInit ( root = document , warn = CONSOLE_WARN ) {
61
+ export function mdcAutoInit ( root = document , warn = CONSOLE_WARN ) {
47
62
const components = [ ] ;
48
- const nodes = root . querySelectorAll ( '[data-mdc-auto-init]' ) ;
49
- for ( let i = 0 , node ; ( node = nodes [ i ] ) ; i ++ ) {
50
- const ctorName = node . dataset . mdcAutoInit ;
63
+ const nodes : Element [ ] = [ ] . slice . call ( root . querySelectorAll ( '[data-mdc-auto-init]' ) ) ;
64
+
65
+ for ( const node of nodes ) {
66
+ const ctorName = node . getAttribute ( 'data-mdc-auto-init' ) ;
51
67
if ( ! ctorName ) {
52
68
throw new Error ( '(mdc-auto-init) Constructor name must be given.' ) ;
53
69
}
54
70
55
- const Ctor = registry [ ctorName ] ;
56
- if ( typeof Ctor !== 'function' ) {
71
+ const Constructor = registry [ ctorName ] ; // tslint:disable-line:variable-name
72
+ if ( typeof Constructor !== 'function' ) {
57
73
throw new Error (
58
74
`(mdc-auto-init) Could not find constructor in registry for ${ ctorName } ` ) ;
59
75
}
60
76
61
- if ( node [ ctorName ] ) {
77
+ if ( Object . getOwnPropertyDescriptor ( node , ctorName ) ) {
62
78
warn ( `(mdc-auto-init) Component already initialized for ${ node } . Skipping...` ) ;
63
79
continue ;
64
80
}
65
81
66
82
// TODO: Should we make an eslint rule for an attachTo() static method?
67
- const component = Ctor . attachTo ( node ) ;
83
+ // See https://github.com/Microsoft/TypeScript/issues/14600 for discussion of static interface support in TS
84
+ const component = Constructor . attachTo ( node ) ;
68
85
Object . defineProperty ( node , ctorName , {
86
+ configurable : true ,
87
+ enumerable : false ,
69
88
value : component ,
70
89
writable : false ,
71
- enumerable : false ,
72
- configurable : true ,
73
90
} ) ;
74
91
components . push ( component ) ;
75
92
}
@@ -78,22 +95,27 @@ export default function mdcAutoInit(root = document, warn = CONSOLE_WARN) {
78
95
return components ;
79
96
}
80
97
81
- mdcAutoInit . register = function ( componentName , Ctor , warn = CONSOLE_WARN ) {
82
- if ( typeof Ctor !== 'function' ) {
83
- throw new Error ( `(mdc-auto-init) Invalid Ctor value ${ Ctor } . Expected function` ) ;
98
+ // Constructor is PascalCased because it is a direct reference to a class, rather than an instance of a class.
99
+ // tslint:disable-next-line:variable-name
100
+ mdcAutoInit . register = function ( componentName : string , Constructor : ComponentClass , warn = CONSOLE_WARN ) {
101
+ if ( typeof Constructor !== 'function' ) {
102
+ throw new Error ( `(mdc-auto-init) Invalid Ctor value ${ Constructor } . Expected function` ) ;
84
103
}
85
104
if ( registry [ componentName ] ) {
86
105
warn (
87
- `(mdc-auto-init) Overriding registration for ${ componentName } with ${ Ctor } . ` +
106
+ `(mdc-auto-init) Overriding registration for ${ componentName } with ${ Constructor } . ` +
88
107
`Was: ${ registry [ componentName ] } ` ) ;
89
108
}
90
- registry [ componentName ] = Ctor ;
109
+ registry [ componentName ] = Constructor ;
91
110
} ;
92
111
93
- mdcAutoInit . deregister = function ( componentName ) {
112
+ mdcAutoInit . deregister = function ( componentName : string ) {
94
113
delete registry [ componentName ] ;
95
114
} ;
96
115
97
116
mdcAutoInit . deregisterAll = function ( ) {
98
- Object . keys ( registry ) . forEach ( this . deregister , this ) ;
117
+ const keys = Object . keys ( registry ) as string [ ] ;
118
+ keys . forEach ( this . deregister , this ) ;
99
119
} ;
120
+
121
+ export default mdcAutoInit ;
0 commit comments