@materializecss/materialize 2.0.3-beta → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +16 -18
  3. package/dist/css/materialize.css +73 -26
  4. package/dist/css/materialize.min.css +3 -3
  5. package/dist/js/materialize.js +560 -2015
  6. package/dist/js/materialize.min.js +3 -3
  7. package/dist/js/materialize.min.js.map +1 -1
  8. package/dist/src/buttons.d.ts.map +1 -1
  9. package/dist/src/cards.d.ts.map +1 -1
  10. package/dist/src/collapsible.d.ts +1 -0
  11. package/dist/src/collapsible.d.ts.map +1 -1
  12. package/dist/src/dropdown.d.ts +1 -0
  13. package/dist/src/dropdown.d.ts.map +1 -1
  14. package/dist/src/global.d.ts.map +1 -1
  15. package/dist/src/materialbox.d.ts +14 -10
  16. package/dist/src/materialbox.d.ts.map +1 -1
  17. package/dist/src/modal.d.ts.map +1 -1
  18. package/dist/src/range.d.ts.map +1 -1
  19. package/dist/src/scrollspy.d.ts.map +1 -1
  20. package/dist/src/sidenav.d.ts +25 -25
  21. package/dist/src/sidenav.d.ts.map +1 -1
  22. package/dist/src/slider.d.ts +12 -12
  23. package/dist/src/slider.d.ts.map +1 -1
  24. package/dist/src/tabs.d.ts +1 -1
  25. package/dist/src/tabs.d.ts.map +1 -1
  26. package/dist/src/toasts.d.ts +7 -2
  27. package/dist/src/toasts.d.ts.map +1 -1
  28. package/dist/src/tooltip.d.ts.map +1 -1
  29. package/package.json +29 -44
  30. package/sass/components/_collapsible.scss +14 -2
  31. package/sass/components/_materialbox.scss +2 -2
  32. package/sass/components/_modal.scss +0 -1
  33. package/sass/components/_tooltip.scss +18 -8
  34. package/sass/components/_variables.scss +2 -2
  35. package/Gruntfile.js +0 -385
  36. package/src/autocomplete.ts +0 -553
  37. package/src/bounding.ts +0 -6
  38. package/src/buttons.ts +0 -260
  39. package/src/cards.ts +0 -53
  40. package/src/carousel.ts +0 -676
  41. package/src/characterCounter.ts +0 -117
  42. package/src/chips.ts +0 -439
  43. package/src/collapsible.ts +0 -249
  44. package/src/component.ts +0 -120
  45. package/src/datepicker.ts +0 -1076
  46. package/src/dropdown.ts +0 -644
  47. package/src/edges.ts +0 -6
  48. package/src/forms.ts +0 -132
  49. package/src/global.ts +0 -114
  50. package/src/index.ts +0 -26
  51. package/src/materialbox.ts +0 -404
  52. package/src/modal.ts +0 -341
  53. package/src/parallax.ts +0 -149
  54. package/src/pushpin.ts +0 -165
  55. package/src/range.ts +0 -198
  56. package/src/scrollspy.ts +0 -263
  57. package/src/select.ts +0 -484
  58. package/src/sidenav.ts +0 -543
  59. package/src/slider.ts +0 -474
  60. package/src/tabs.ts +0 -347
  61. package/src/tapTarget.ts +0 -273
  62. package/src/timepicker.ts +0 -832
  63. package/src/toasts.ts +0 -290
  64. package/src/tooltip.ts +0 -366
  65. package/src/utils.ts +0 -271
  66. package/src/waves.ts +0 -70
package/src/modal.ts DELETED
@@ -1,341 +0,0 @@
1
- import anim from "animejs";
2
-
3
- import { Utils } from "./utils";
4
- import { Component, BaseOptions, InitElements, MElement } from "./component";
5
-
6
- export interface ModalOptions extends BaseOptions {
7
- /**
8
- * Opacity of the modal overlay.
9
- * @default 0.5
10
- */
11
- opacity: number;
12
- /**
13
- * Transition in duration in milliseconds.
14
- * @default 250
15
- */
16
- inDuration: number;
17
- /**
18
- * Transition out duration in milliseconds.
19
- * @default 250
20
- */
21
- outDuration: number;
22
- /**
23
- * Prevent page from scrolling while modal is open.
24
- * @default true
25
- */
26
- preventScrolling: boolean;
27
- /**
28
- * Callback function called before modal is opened.
29
- * @default null
30
- */
31
- onOpenStart: (this: Modal, el: HTMLElement) => void;
32
- /**
33
- * Callback function called after modal is opened.
34
- * @default null
35
- */
36
- onOpenEnd: (this: Modal, el: HTMLElement) => void;
37
- /**
38
- * Callback function called before modal is closed.
39
- * @default null
40
- */
41
- onCloseStart: (el: HTMLElement) => void;
42
- /**
43
- * Callback function called after modal is closed.
44
- * @default null
45
- */
46
- onCloseEnd: (el: HTMLElement) => void;
47
- /**
48
- * Allow modal to be dismissed by keyboard or overlay click.
49
- * @default true
50
- */
51
- dismissible: boolean;
52
- /**
53
- * Starting top offset.
54
- * @default '4%'
55
- */
56
- startingTop: string;
57
- /**
58
- * Ending top offset.
59
- * @default '10%'
60
- */
61
- endingTop: string;
62
- }
63
-
64
- const _defaults = {
65
- opacity: 0.5,
66
- inDuration: 250,
67
- outDuration: 250,
68
- onOpenStart: null,
69
- onOpenEnd: null,
70
- onCloseStart: null,
71
- onCloseEnd: null,
72
- preventScrolling: true,
73
- dismissible: true,
74
- startingTop: '4%',
75
- endingTop: '10%'
76
- };
77
-
78
- export class Modal extends Component<ModalOptions> {
79
-
80
- static _modalsOpen: number;
81
- static _count: number;
82
-
83
- /**
84
- * ID of the modal element.
85
- */
86
- id: string;
87
- /**
88
- * If the modal is open.
89
- */
90
- isOpen: boolean;
91
-
92
- private _openingTrigger: any;
93
- private _overlay: HTMLElement;
94
- private _nthModalOpened: number;
95
-
96
- constructor(el: HTMLElement, options: Partial<ModalOptions>) {
97
- super(el, options, Modal);
98
- (this.el as any).M_Modal = this;
99
-
100
- this.options = {
101
- ...Modal.defaults,
102
- ...options
103
- };
104
-
105
- this.isOpen = false;
106
- this.id = this.el.id;
107
- this._openingTrigger = undefined;
108
- this._overlay = document.createElement('div');
109
- this._overlay.classList.add('modal-overlay');
110
- this.el.tabIndex = 0;
111
- this._nthModalOpened = 0;
112
- Modal._count++;
113
- this._setupEventHandlers();
114
- }
115
-
116
- static get defaults() {
117
- return _defaults;
118
- }
119
-
120
- /**
121
- * Initializes instance of Modal.
122
- * @param el HTML element.
123
- * @param options Component options.
124
- */
125
- static init(el: HTMLElement, options?: Partial<ModalOptions>): Modal;
126
- /**
127
- * Initializes instances of Modal.
128
- * @param els HTML elements.
129
- * @param options Component options.
130
- */
131
- static init(els: InitElements<MElement>, options?: Partial<ModalOptions>): Modal[];
132
- /**
133
- * Initializes instances of Modal.
134
- * @param els HTML elements.
135
- * @param options Component options.
136
- */
137
- static init(els: HTMLElement | InitElements<MElement>, options: Partial<ModalOptions> = {}): Modal | Modal[] {
138
- return super.init(els, options, Modal);
139
- }
140
-
141
- static getInstance(el: HTMLElement): Modal {
142
- return (el as any).M_Modal;
143
- }
144
-
145
- destroy() {
146
- Modal._count--;
147
- this._removeEventHandlers();
148
- this.el.removeAttribute('style');
149
- this._overlay.remove();
150
- (this.el as any).M_Modal = undefined;
151
- }
152
-
153
- _setupEventHandlers() {
154
- if (Modal._count === 1) {
155
- document.body.addEventListener('click', this._handleTriggerClick);
156
- }
157
- this._overlay.addEventListener('click', this._handleOverlayClick);
158
- this.el.addEventListener('click', this._handleModalCloseClick);
159
- }
160
-
161
- _removeEventHandlers() {
162
- if (Modal._count === 0) {
163
- document.body.removeEventListener('click', this._handleTriggerClick);
164
- }
165
- this._overlay.removeEventListener('click', this._handleOverlayClick);
166
- this.el.removeEventListener('click', this._handleModalCloseClick);
167
- }
168
-
169
- _handleTriggerClick = (e: MouseEvent) => {
170
- const trigger = (e.target as HTMLElement).closest('.modal-trigger');
171
- if (!trigger) return;
172
- const modalId = Utils.getIdFromTrigger(trigger as HTMLElement);
173
- const modalInstance = (document.getElementById(modalId) as any).M_Modal;
174
- if (modalInstance) modalInstance.open(trigger);
175
- e.preventDefault();
176
- }
177
-
178
- _handleOverlayClick = () => {
179
- if (this.options.dismissible) this.close();
180
- }
181
-
182
- _handleModalCloseClick = (e: MouseEvent) => {
183
- const closeTrigger = (e.target as HTMLElement).closest('.modal-close');
184
- if (closeTrigger) this.close();
185
- }
186
-
187
- _handleKeydown = (e: KeyboardEvent) => {
188
- if (Utils.keys.ESC.includes(e.key) && this.options.dismissible) this.close();
189
- }
190
-
191
- _handleFocus = (e: FocusEvent) => {
192
- // Only trap focus if this modal is the last model opened (prevents loops in nested modals).
193
- if (!this.el.contains(e.target as HTMLElement) && this._nthModalOpened === Modal._modalsOpen) {
194
- this.el.focus();
195
- }
196
- }
197
-
198
- _animateIn() {
199
- // Set initial styles
200
- this.el.style.display = 'block';
201
- this.el.style.opacity = '0';
202
- this._overlay.style.display = 'block';
203
- this._overlay.style.opacity = '0';
204
- // Animate overlay
205
- anim({
206
- targets: this._overlay,
207
- opacity: this.options.opacity,
208
- duration: this.options.inDuration,
209
- easing: 'easeOutQuad'
210
- });
211
- // Define modal animation options
212
- const enterAnimOptions = {
213
- targets: this.el,
214
- duration: this.options.inDuration,
215
- easing: 'easeOutCubic',
216
- // Handle modal onOpenEnd callback
217
- complete: () => {
218
- if (typeof this.options.onOpenEnd === 'function') {
219
- this.options.onOpenEnd.call(this, this.el, this._openingTrigger);
220
- }
221
- }
222
- };
223
- // Bottom sheet animation
224
- if (this.el.classList.contains('bottom-sheet')) {
225
- enterAnimOptions['bottom'] = 0;
226
- enterAnimOptions['opacity'] = 1;
227
- }
228
- // Normal modal animation
229
- else {
230
- enterAnimOptions['top'] = [this.options.startingTop, this.options.endingTop];
231
- enterAnimOptions['opacity'] = 1;
232
- enterAnimOptions['scaleX'] = [0.8, 1];
233
- enterAnimOptions['scaleY'] = [0.8, 1];
234
- }
235
- anim(enterAnimOptions);
236
- }
237
-
238
- _animateOut() {
239
- // Animate overlay
240
- anim({
241
- targets: this._overlay,
242
- opacity: 0,
243
- duration: this.options.outDuration,
244
- easing: 'easeOutQuart'
245
- });
246
- // Define modal animation options
247
- const exitAnimOptions = {
248
- targets: this.el,
249
- duration: this.options.outDuration,
250
- easing: 'easeOutCubic',
251
- // Handle modal ready callback
252
- complete: () => {
253
- this.el.style.display = 'none';
254
- this._overlay.remove();
255
- // Call onCloseEnd callback
256
- if (typeof this.options.onCloseEnd === 'function') {
257
- this.options.onCloseEnd.call(this, this.el);
258
- }
259
- }
260
- };
261
- // Bottom sheet animation
262
- if (this.el.classList.contains('bottom-sheet')) {
263
- exitAnimOptions['bottom'] = '-100%';
264
- exitAnimOptions['opacity'] = 0;
265
- }
266
- // Normal modal animation
267
- else {
268
- exitAnimOptions['top'] = [this.options.endingTop, this.options.startingTop];
269
- exitAnimOptions['opacity'] = 0;
270
- exitAnimOptions['scaleX'] = 0.8;
271
- exitAnimOptions['scaleY'] = 0.8;
272
- }
273
- anim(exitAnimOptions);
274
- }
275
-
276
- /**
277
- * Open modal.
278
- */
279
- open = (trigger?: HTMLElement): Modal => {
280
- if (this.isOpen) return;
281
- this.isOpen = true;
282
- Modal._modalsOpen++;
283
- this._nthModalOpened = Modal._modalsOpen;
284
- // Set Z-Index based on number of currently open modals
285
- this._overlay.style.zIndex = (1000 + Modal._modalsOpen * 2).toString();
286
- this.el.style.zIndex = (1000 + Modal._modalsOpen * 2 + 1).toString();
287
- // Set opening trigger, undefined indicates modal was opened by javascript
288
- this._openingTrigger = !!trigger ? trigger : undefined;
289
- // onOpenStart callback
290
- if (typeof this.options.onOpenStart === 'function') {
291
- this.options.onOpenStart.call(this, this.el, this._openingTrigger);
292
- }
293
- if (this.options.preventScrolling) {
294
- document.body.style.overflow = 'hidden';
295
- }
296
- this.el.classList.add('open');
297
- this.el.insertAdjacentElement('afterend', this._overlay);
298
- if (this.options.dismissible) {
299
- document.addEventListener('keydown', this._handleKeydown);
300
- document.addEventListener('focus', this._handleFocus, true);
301
- }
302
- anim.remove(this.el);
303
- anim.remove(this._overlay);
304
- this._animateIn();
305
- // Focus modal
306
- this.el.focus();
307
- return this;
308
- }
309
-
310
- /**
311
- * Close modal.
312
- */
313
- close = () => {
314
- if (!this.isOpen) return;
315
- this.isOpen = false;
316
- Modal._modalsOpen--;
317
- this._nthModalOpened = 0;
318
- // Call onCloseStart callback
319
- if (typeof this.options.onCloseStart === 'function') {
320
- this.options.onCloseStart.call(this, this.el);
321
- }
322
- this.el.classList.remove('open');
323
- // Enable body scrolling only if there are no more modals open.
324
- if (Modal._modalsOpen === 0) {
325
- document.body.style.overflow = '';
326
- }
327
- if (this.options.dismissible) {
328
- document.removeEventListener('keydown', this._handleKeydown);
329
- document.removeEventListener('focus', this._handleFocus, true);
330
- }
331
- anim.remove(this.el);
332
- anim.remove(this._overlay);
333
- this._animateOut();
334
- return this;
335
- }
336
-
337
- static{
338
- Modal._modalsOpen = 0;
339
- Modal._count = 0;
340
- }
341
- }
package/src/parallax.ts DELETED
@@ -1,149 +0,0 @@
1
- import { Utils } from "./utils";
2
- import { Component, BaseOptions, InitElements, MElement } from "./component";
3
-
4
- export interface ParallaxOptions extends BaseOptions {
5
- /**
6
- * The minimum width of the screen, in pixels, where the parallax functionality starts working.
7
- * @default 0
8
- */
9
- responsiveThreshold: number;
10
- }
11
-
12
- let _defaults: ParallaxOptions = {
13
- responsiveThreshold: 0 // breakpoint for swipeable
14
- };
15
-
16
- export class Parallax extends Component<ParallaxOptions> {
17
- private _enabled: boolean;
18
- private _img: HTMLImageElement;
19
- static _parallaxes: Parallax[] = [];
20
- static _handleScrollThrottled: () => any;
21
- static _handleWindowResizeThrottled: () => any;
22
-
23
- constructor(el: HTMLElement, options: Partial<ParallaxOptions>) {
24
- super(el, options, Parallax);
25
- (this.el as any).M_Parallax = this;
26
-
27
- this.options = {
28
- ...Parallax.defaults,
29
- ...options
30
- };
31
-
32
- this._enabled = window.innerWidth > this.options.responsiveThreshold;
33
- this._img = this.el.querySelector('img');
34
- this._updateParallax();
35
- this._setupEventHandlers();
36
- this._setupStyles();
37
- Parallax._parallaxes.push(this);
38
- }
39
-
40
- static get defaults(): ParallaxOptions {
41
- return _defaults;
42
- }
43
-
44
- /**
45
- * Initializes instance of Parallax.
46
- * @param el HTML element.
47
- * @param options Component options.
48
- */
49
- static init(el: HTMLElement, options?: Partial<ParallaxOptions>): Parallax;
50
- /**
51
- * Initializes instances of Parallax.
52
- * @param els HTML elements.
53
- * @param options Component options.
54
- */
55
- static init(els: InitElements<MElement>, options?: Partial<ParallaxOptions>): Parallax[];
56
- /**
57
- * Initializes instances of Parallax.
58
- * @param els HTML elements.
59
- * @param options Component options.
60
- */
61
- static init(els: HTMLElement | InitElements<MElement>, options: Partial<ParallaxOptions> = {}): Parallax | Parallax[] {
62
- return super.init(els, options, Parallax);
63
- }
64
-
65
- static getInstance(el: HTMLElement): Parallax {
66
- return (el as any).M_Parallax;
67
- }
68
-
69
- destroy() {
70
- Parallax._parallaxes.splice(Parallax._parallaxes.indexOf(this), 1);
71
- this._img.style.transform = '';
72
- this._removeEventHandlers();
73
- (this.el as any).M_Parallax = undefined;
74
- }
75
-
76
- static _handleScroll() {
77
- for (let i = 0; i < Parallax._parallaxes.length; i++) {
78
- let parallaxInstance = Parallax._parallaxes[i];
79
- parallaxInstance._updateParallax.call(parallaxInstance);
80
- }
81
- }
82
-
83
- static _handleWindowResize() {
84
- for (let i = 0; i < Parallax._parallaxes.length; i++) {
85
- let parallaxInstance = Parallax._parallaxes[i];
86
- parallaxInstance._enabled =
87
- window.innerWidth > parallaxInstance.options.responsiveThreshold;
88
- }
89
- }
90
-
91
- _setupEventHandlers() {
92
- this._img.addEventListener('load', this._handleImageLoad);
93
- if (Parallax._parallaxes.length === 0) {
94
- if (!Parallax._handleScrollThrottled){
95
- Parallax._handleScrollThrottled = Utils.throttle(Parallax._handleScroll, 5);
96
- }
97
- if (!Parallax._handleWindowResizeThrottled){
98
- Parallax._handleWindowResizeThrottled = Utils.throttle(Parallax._handleWindowResize, 5);
99
- }
100
- window.addEventListener('scroll', Parallax._handleScrollThrottled);
101
- window.addEventListener('resize', Parallax._handleWindowResizeThrottled);
102
- }
103
- }
104
-
105
- _removeEventHandlers() {
106
- this._img.removeEventListener('load', this._handleImageLoad);
107
- if (Parallax._parallaxes.length === 0) {
108
- window.removeEventListener('scroll', Parallax._handleScrollThrottled);
109
- window.removeEventListener('resize', Parallax._handleWindowResizeThrottled);
110
- }
111
- }
112
-
113
- _setupStyles() {
114
- this._img.style.opacity = '1';
115
- }
116
-
117
- _handleImageLoad = () => {
118
- this._updateParallax();
119
- }
120
-
121
- private _offset(el: Element) {
122
- const box = el.getBoundingClientRect();
123
- const docElem = document.documentElement;
124
- return {
125
- top: box.top + window.pageYOffset - docElem.clientTop,
126
- left: box.left + window.pageXOffset - docElem.clientLeft
127
- };
128
- }
129
-
130
- _updateParallax() {
131
- const containerHeight = this.el.getBoundingClientRect().height > 0 ? (this.el.parentNode as any).offsetHeight : 500;
132
- const imgHeight = this._img.offsetHeight;
133
- const parallaxDist = imgHeight - containerHeight;
134
- const bottom = this._offset(this.el).top + containerHeight;
135
- const top = this._offset(this.el).top;
136
- const scrollTop = Utils.getDocumentScrollTop();
137
- const windowHeight = window.innerHeight;
138
- const windowBottom = scrollTop + windowHeight;
139
- const percentScrolled = (windowBottom - top) / (containerHeight + windowHeight);
140
- const parallax = parallaxDist * percentScrolled;
141
-
142
- if (!this._enabled) {
143
- this._img.style.transform = '';
144
- }
145
- else if (bottom > scrollTop && top < scrollTop + windowHeight) {
146
- this._img.style.transform = `translate3D(-50%, ${parallax}px, 0)`;
147
- }
148
- }
149
- }
package/src/pushpin.ts DELETED
@@ -1,165 +0,0 @@
1
- import { Utils } from "./utils";
2
- import { Component, BaseOptions, InitElements, MElement } from "./component";
3
-
4
- export interface PushpinOptions extends BaseOptions {
5
- /**
6
- * The distance in pixels from the top of the page where
7
- * the element becomes fixed.
8
- * @default 0
9
- */
10
- top: number;
11
- /**
12
- * The distance in pixels from the top of the page where
13
- * the elements stops being fixed.
14
- * @default Infinity
15
- */
16
- bottom: number;
17
- /**
18
- * The offset from the top the element will be fixed at.
19
- * @default 0
20
- */
21
- offset: number;
22
- /**
23
- * Callback function called when pushpin position changes.
24
- * You are provided with a position string.
25
- * @default null
26
- */
27
- onPositionChange: (position: "pinned" | "pin-top" | "pin-bottom") => void;
28
- }
29
-
30
- let _defaults = {
31
- top: 0,
32
- bottom: Infinity,
33
- offset: 0,
34
- onPositionChange: null
35
- };
36
-
37
- export class Pushpin extends Component<PushpinOptions> {
38
- static _pushpins: any[];
39
- originalOffset: any;
40
-
41
- constructor(el: HTMLElement, options: Partial<PushpinOptions>) {
42
- super(el, options, Pushpin);
43
- (this.el as any).M_Pushpin = this;
44
-
45
- this.options = {
46
- ...Pushpin.defaults,
47
- ...options
48
- };
49
-
50
- this.originalOffset = (this.el as HTMLElement).offsetTop;
51
- Pushpin._pushpins.push(this);
52
- this._setupEventHandlers();
53
- this._updatePosition();
54
- }
55
-
56
- static get defaults(): PushpinOptions {
57
- return _defaults;
58
- }
59
-
60
- /**
61
- * Initializes instance of Pushpin.
62
- * @param el HTML element.
63
- * @param options Component options.
64
- */
65
- static init(el: HTMLElement, options?: Partial<PushpinOptions>): Pushpin;
66
- /**
67
- * Initializes instances of Pushpin.
68
- * @param els HTML elements.
69
- * @param options Component options.
70
- */
71
- static init(els: InitElements<MElement>, options?: Partial<PushpinOptions>): Pushpin[];
72
- /**
73
- * Initializes instances of Pushpin.
74
- * @param els HTML elements.
75
- * @param options Component options.
76
- */
77
- static init(els: HTMLElement | InitElements<MElement>, options: Partial<PushpinOptions> = {}): Pushpin | Pushpin[] {
78
- return super.init(els, options, Pushpin);
79
- }
80
-
81
- static getInstance(el: HTMLElement): Pushpin {
82
- return (el as any).M_Pushpin;
83
- }
84
-
85
- destroy() {
86
- (this.el as HTMLElement).style.top = null;
87
- this._removePinClasses();
88
- // Remove pushpin Inst
89
- let index = Pushpin._pushpins.indexOf(this);
90
- Pushpin._pushpins.splice(index, 1);
91
- if (Pushpin._pushpins.length === 0) {
92
- this._removeEventHandlers();
93
- }
94
- (this.el as any).M_Pushpin = undefined;
95
- }
96
-
97
- static _updateElements() {
98
- for (let elIndex in Pushpin._pushpins) {
99
- let pInstance = Pushpin._pushpins[elIndex];
100
- pInstance._updatePosition();
101
- }
102
- }
103
-
104
- _setupEventHandlers() {
105
- document.addEventListener('scroll', Pushpin._updateElements);
106
- }
107
-
108
- _removeEventHandlers() {
109
- document.removeEventListener('scroll', Pushpin._updateElements);
110
- }
111
-
112
- _updatePosition() {
113
- let scrolled = Utils.getDocumentScrollTop() + this.options.offset;
114
-
115
- if (
116
- this.options.top <= scrolled &&
117
- this.options.bottom >= scrolled &&
118
- !this.el.classList.contains('pinned')
119
- ) {
120
- this._removePinClasses();
121
- (this.el as HTMLElement).style.top = `${this.options.offset}px`;
122
- this.el.classList.add('pinned');
123
-
124
- // onPositionChange callback
125
- if (typeof this.options.onPositionChange === 'function') {
126
- this.options.onPositionChange.call(this, 'pinned');
127
- }
128
- }
129
-
130
- // Add pin-top (when scrolled position is above top)
131
- if (scrolled < this.options.top && !this.el.classList.contains('pin-top')) {
132
- this._removePinClasses();
133
- (this.el as HTMLElement).style.top = '0';
134
- this.el.classList.add('pin-top');
135
-
136
- // onPositionChange callback
137
- if (typeof this.options.onPositionChange === 'function') {
138
- this.options.onPositionChange.call(this, 'pin-top');
139
- }
140
- }
141
-
142
- // Add pin-bottom (when scrolled position is below bottom)
143
- if (scrolled > this.options.bottom && !this.el.classList.contains('pin-bottom')) {
144
- this._removePinClasses();
145
- this.el.classList.add('pin-bottom');
146
- (this.el as HTMLElement).style.top = `${this.options.bottom - this.originalOffset}px`;
147
-
148
- // onPositionChange callback
149
- if (typeof this.options.onPositionChange === 'function') {
150
- this.options.onPositionChange.call(this, 'pin-bottom');
151
- }
152
- }
153
- }
154
-
155
- _removePinClasses() {
156
- // IE 11 bug (can't remove multiple classes in one line)
157
- this.el.classList.remove('pin-top');
158
- this.el.classList.remove('pinned');
159
- this.el.classList.remove('pin-bottom');
160
- }
161
-
162
- static {
163
- Pushpin._pushpins = [];
164
- }
165
- }