@materializecss/materialize 1.2.2 → 2.0.1-alpha

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 (90) hide show
  1. package/Gruntfile.js +68 -313
  2. package/README.md +26 -14
  3. package/dist/css/materialize.css +1009 -1822
  4. package/dist/css/materialize.min.css +2 -8
  5. package/dist/js/materialize.js +8414 -12299
  6. package/dist/js/materialize.min.js +8968 -2
  7. package/dist/js/materialize.min.js.map +1 -0
  8. package/package.json +13 -9
  9. package/sass/components/_badges.scss +12 -2
  10. package/sass/components/_buttons.scss +16 -11
  11. package/sass/components/_cards.scss +14 -9
  12. package/sass/components/_carousel.scss +5 -2
  13. package/sass/components/_chips.scss +3 -3
  14. package/sass/components/_collapsible.scss +22 -8
  15. package/sass/components/_collection.scss +14 -6
  16. package/sass/components/_datepicker.scss +30 -11
  17. package/sass/components/_dropdown.scss +6 -4
  18. package/sass/components/_global.scss +132 -111
  19. package/sass/components/_grid.scss +119 -98
  20. package/sass/components/_modal.scss +3 -3
  21. package/sass/components/_navbar.scss +31 -17
  22. package/sass/components/_normalize.scss +26 -124
  23. package/sass/components/_sidenav.scss +21 -20
  24. package/sass/components/_slider.scss +27 -7
  25. package/sass/components/_table_of_contents.scss +12 -12
  26. package/sass/components/_tabs.scss +47 -16
  27. package/sass/components/_tapTarget.scss +6 -6
  28. package/sass/components/_theme_variables.scss +98 -0
  29. package/sass/components/_timepicker.scss +54 -46
  30. package/sass/components/_toast.scss +3 -3
  31. package/sass/components/_tooltip.scss +4 -5
  32. package/sass/components/_typography.scss +1 -1
  33. package/sass/components/_variables.scss +185 -120
  34. package/sass/components/forms/_checkboxes.scss +9 -9
  35. package/sass/components/forms/_file-input.scss +9 -7
  36. package/sass/components/forms/_input-fields.scss +173 -234
  37. package/sass/components/forms/_radio-buttons.scss +1 -1
  38. package/sass/components/forms/_range.scss +11 -11
  39. package/sass/components/forms/_select.scss +29 -19
  40. package/sass/components/forms/_switches.scss +22 -18
  41. package/sass/materialize.scss +1 -1
  42. package/src/autocomplete.ts +459 -0
  43. package/src/bounding.ts +6 -0
  44. package/{js/buttons.js → src/buttons.ts} +103 -162
  45. package/src/cards.ts +54 -0
  46. package/{js/carousel.js → src/carousel.ts} +137 -262
  47. package/src/characterCounter.ts +88 -0
  48. package/src/chips.ts +350 -0
  49. package/src/collapsible.ts +184 -0
  50. package/{js/component.js → src/component.ts} +6 -19
  51. package/{js/datepicker.js → src/datepicker.ts} +213 -299
  52. package/{js/dropdown.js → src/dropdown.ts} +140 -254
  53. package/src/edges.ts +6 -0
  54. package/src/forms.ts +120 -0
  55. package/src/global.ts +385 -0
  56. package/src/materialbox.ts +348 -0
  57. package/src/modal.ts +256 -0
  58. package/{js/parallax.js → src/parallax.ts} +47 -60
  59. package/{js/pushpin.js → src/pushpin.ts} +19 -47
  60. package/{js/range.js → src/range.ts} +58 -139
  61. package/{js/scrollspy.js → src/scrollspy.ts} +81 -153
  62. package/src/select.ts +448 -0
  63. package/{js/sidenav.js → src/sidenav.ts} +96 -202
  64. package/src/slider.ts +415 -0
  65. package/src/tabs.ts +293 -0
  66. package/src/tapTarget.ts +240 -0
  67. package/{js/timepicker.js → src/timepicker.ts} +268 -272
  68. package/{js/toasts.js → src/toasts.ts} +75 -134
  69. package/{js/tooltip.js → src/tooltip.ts} +59 -96
  70. package/src/waves.ts +70 -0
  71. package/extras/noUiSlider/nouislider.css +0 -404
  72. package/extras/noUiSlider/nouislider.js +0 -2147
  73. package/extras/noUiSlider/nouislider.min.js +0 -1
  74. package/js/anime.min.js +0 -34
  75. package/js/autocomplete.js +0 -479
  76. package/js/cards.js +0 -40
  77. package/js/cash.js +0 -960
  78. package/js/characterCounter.js +0 -136
  79. package/js/chips.js +0 -486
  80. package/js/collapsible.js +0 -275
  81. package/js/forms.js +0 -285
  82. package/js/global.js +0 -428
  83. package/js/materialbox.js +0 -453
  84. package/js/modal.js +0 -382
  85. package/js/select.js +0 -391
  86. package/js/slider.js +0 -497
  87. package/js/tabs.js +0 -402
  88. package/js/tapTarget.js +0 -315
  89. package/js/waves.js +0 -615
  90. package/sass/components/_waves.scss +0 -187
package/src/forms.ts ADDED
@@ -0,0 +1,120 @@
1
+ import { M } from "./global";
2
+
3
+ export class Forms {
4
+
5
+ static textareaAutoResize(textarea: HTMLTextAreaElement) {
6
+ if (!textarea) {
7
+ console.error('No textarea element found');
8
+ return;
9
+ }
10
+ // Textarea Auto Resize
11
+ let hiddenDiv: HTMLDivElement = document.querySelector('.hiddendiv');
12
+ if (!hiddenDiv) {
13
+ hiddenDiv = document.createElement('div');
14
+ hiddenDiv.classList.add('hiddendiv', 'common');
15
+ document.body.append(hiddenDiv);
16
+ }
17
+ const style = getComputedStyle(textarea);
18
+ // Set font properties of hiddenDiv
19
+ const fontFamily = style.fontFamily; //textarea.css('font-family');
20
+ const fontSize = style.fontSize; //textarea.css('font-size');
21
+ const lineHeight = style.lineHeight; //textarea.css('line-height');
22
+ // Firefox can't handle padding shorthand.
23
+ const paddingTop = style.paddingTop; //getComputedStyle(textarea).css('padding-top');
24
+ const paddingRight = style.paddingRight; //textarea.css('padding-right');
25
+ const paddingBottom = style.paddingBottom; //textarea.css('padding-bottom');
26
+ const paddingLeft = style.paddingLeft; //textarea.css('padding-left');
27
+
28
+ if (fontSize) hiddenDiv.style.fontSize = fontSize; //('font-size', fontSize);
29
+ if (fontFamily) hiddenDiv.style.fontFamily = fontFamily; //css('font-family', fontFamily);
30
+ if (lineHeight) hiddenDiv.style.lineHeight = lineHeight; //css('line-height', lineHeight);
31
+ if (paddingTop) hiddenDiv.style.paddingTop = paddingTop; //ss('padding-top', paddingTop);
32
+ if (paddingRight) hiddenDiv.style.paddingRight = paddingRight; //css('padding-right', paddingRight);
33
+ if (paddingBottom) hiddenDiv.style.paddingBottom = paddingBottom; //css('padding-bottom', paddingBottom);
34
+ if (paddingLeft) hiddenDiv.style.paddingLeft = paddingLeft; //css('padding-left', paddingLeft);
35
+
36
+ // Set original-height, if none
37
+ if (!textarea.hasAttribute('original-height'))
38
+ textarea.setAttribute('original-height', textarea.getBoundingClientRect().height.toString());
39
+
40
+ if (textarea.getAttribute('wrap') === 'off') {
41
+ hiddenDiv.style.overflowWrap = 'normal'; // ('overflow-wrap', 'normal')
42
+ hiddenDiv.style.whiteSpace = 'pre'; //.css('white-space', 'pre');
43
+ }
44
+
45
+ hiddenDiv.innerText = textarea.value + '\n';
46
+
47
+ const content = hiddenDiv.innerHTML.replace(/\n/g, '<br>');
48
+ hiddenDiv.innerHTML = content;
49
+
50
+ // When textarea is hidden, width goes crazy.
51
+ // Approximate with half of window size
52
+ if (textarea.offsetWidth > 0 && textarea.offsetHeight > 0) {
53
+ hiddenDiv.style.width = textarea.getBoundingClientRect().width +'px'; // ('width', textarea.width() + 'px');
54
+ }
55
+ else {
56
+ hiddenDiv.style.width = (window.innerWidth / 2)+'px' //css('width', window.innerWidth / 2 + 'px');
57
+ }
58
+
59
+ // Resize if the new height is greater than the
60
+ // original height of the textarea
61
+ const originalHeight = parseInt(textarea.getAttribute('original-height'));
62
+ const prevLength = parseInt(textarea.getAttribute('previous-length'));
63
+ if (isNaN(originalHeight)) return;
64
+ if (originalHeight <= hiddenDiv.clientHeight) {
65
+ textarea.style.height = hiddenDiv.clientHeight+'px'; //css('height', hiddenDiv.innerHeight() + 'px');
66
+ }
67
+ else if (textarea.value.length < prevLength) {
68
+ // In case the new height is less than original height, it
69
+ // means the textarea has less text than before
70
+ // So we set the height to the original one
71
+ textarea.style.height = originalHeight+'px';
72
+ }
73
+ textarea.setAttribute('previous-length', textarea.value.length.toString());
74
+ };
75
+
76
+ static Init(){
77
+ document.addEventListener("DOMContentLoaded", () => {
78
+
79
+ document.addEventListener('keyup', e => {
80
+ const target = <HTMLInputElement>e.target;
81
+ // Radio and Checkbox focus class
82
+ if (target instanceof HTMLInputElement && ['radio','checkbox'].includes(target.type)) {
83
+ // TAB, check if tabbing to radio or checkbox.
84
+ if (e.which === M.keys.TAB) {
85
+ target.classList.add('tabbed');
86
+ target.addEventListener('blur', e => target.classList.remove('tabbed'), {once: true});
87
+ }
88
+ }
89
+ });
90
+
91
+ document.querySelectorAll('.materialize-textarea').forEach((textArea: HTMLTextAreaElement) => {
92
+ // Save Data in Element
93
+ textArea.setAttribute('original-height', textArea.getBoundingClientRect().height.toString());
94
+ textArea.setAttribute('previous-length', textArea.value.length.toString());
95
+ Forms.textareaAutoResize(textArea);
96
+
97
+ textArea.addEventListener('keyup', e => Forms.textareaAutoResize(textArea));
98
+ textArea.addEventListener('keydown', e => Forms.textareaAutoResize(textArea));
99
+ });
100
+
101
+ // File Input Path
102
+ document.querySelectorAll('.file-field input[type="file"]').forEach((fileInput: HTMLInputElement) => {
103
+ fileInput.addEventListener('change', e => {
104
+ const fileField = fileInput.closest('.file-field');
105
+ const pathInput = <HTMLInputElement>fileField.querySelector('input.file-path');
106
+ const files = fileInput.files;
107
+ const filenames = [];
108
+ for (let i = 0; i < files.length; i++) {
109
+ filenames.push(files[i].name);
110
+ }
111
+ pathInput.value = filenames.join(', ');
112
+ pathInput.dispatchEvent(new Event('change'));
113
+ });
114
+ });
115
+
116
+ });
117
+ }
118
+ }
119
+
120
+
package/src/global.ts ADDED
@@ -0,0 +1,385 @@
1
+ import { Autocomplete } from './autocomplete';
2
+ import { Bounding } from './bounding';
3
+ import { FloatingActionButton } from './buttons';
4
+ import { Cards } from './cards';
5
+ import { Carousel } from './carousel';
6
+ import { CharacterCounter } from './characterCounter';
7
+ import { Chips } from './chips';
8
+ import { Collapsible } from './collapsible';
9
+ import { Datepicker } from './datepicker';
10
+ import { Dropdown } from './dropdown';
11
+ import { Edges } from './edges';
12
+ import { Forms } from './forms';
13
+ import { Materialbox } from './materialbox';
14
+ import { Modal } from './modal';
15
+ import { Parallax } from './parallax';
16
+ import { Pushpin } from './pushpin';
17
+ import { ScrollSpy } from './scrollspy';
18
+ import { FormSelect } from './select';
19
+ import { Sidenav } from './sidenav';
20
+ import { Slider } from './slider';
21
+ import { Tabs } from './tabs';
22
+ import { TapTarget } from './tapTarget';
23
+ import { Timepicker } from './timepicker';
24
+ import { Toast } from './toasts';
25
+ import { Tooltip } from './tooltip';
26
+ import { Waves } from './waves';
27
+ import { Range } from './range';
28
+
29
+ export class M {
30
+ static version = '2.0.1-alpha';
31
+
32
+ static keys = {
33
+ TAB: 9,
34
+ ENTER: 13,
35
+ ESC: 27,
36
+ ARROW_UP: 38,
37
+ ARROW_DOWN: 40
38
+ };
39
+
40
+ static Autocomplete: typeof Autocomplete = Autocomplete;
41
+ static Tabs: typeof Tabs = Tabs;
42
+ static Carousel: typeof Carousel = Carousel;
43
+ static Dropdown: typeof Dropdown = Dropdown;
44
+ static FloatingActionButton: typeof FloatingActionButton = FloatingActionButton;
45
+ static Chips: typeof Chips = Chips;
46
+ static Collapsible: typeof Collapsible = Collapsible;
47
+ static Datepicker: typeof Datepicker = Datepicker;
48
+ static CharacterCounter: typeof CharacterCounter = CharacterCounter;
49
+ static FormSelect: typeof FormSelect = FormSelect;
50
+ static Modal: typeof Modal = Modal;
51
+ static Pushpin: typeof Pushpin = Pushpin;
52
+ static Materialbox: typeof Materialbox = Materialbox;
53
+ static Parallax: typeof Parallax = Parallax;
54
+ static Slider: typeof Slider = Slider;
55
+ static Timepicker: typeof Timepicker = Timepicker;
56
+ static toast: (opt: any) => Toast = (opt) => new Toast(opt) ;
57
+ static Tooltip: typeof Tooltip = Tooltip;
58
+ static Sidenav: typeof Sidenav = Sidenav;
59
+ static TapTarget: typeof TapTarget = TapTarget;
60
+ static ScrollSpy: typeof ScrollSpy = ScrollSpy;
61
+ static Range: typeof Range = Range;
62
+ static Waves: typeof Waves = Waves;
63
+
64
+ static tabPressed:boolean = false;
65
+ static keyDown:boolean = false;
66
+
67
+ static docHandleKeydown(e) {
68
+ M.keyDown = true;
69
+ if (e.which === M.keys.TAB || e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) {
70
+ M.tabPressed = true;
71
+ }
72
+ }
73
+
74
+ static docHandleKeyup(e) {
75
+ M.keyDown = false;
76
+ if (e.which === M.keys.TAB || e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) {
77
+ M.tabPressed = false;
78
+ }
79
+ }
80
+
81
+ static docHandleFocus(e) {
82
+ if (M.keyDown) {
83
+ document.body.classList.add('keyboard-focused');
84
+ }
85
+ }
86
+
87
+ static docHandleBlur(e) {
88
+ document.body.classList.remove('keyboard-focused');
89
+ }
90
+
91
+ static {
92
+ document.addEventListener('keydown', this.docHandleKeydown, true);
93
+ document.addEventListener('keyup', this.docHandleKeyup, true);
94
+ document.addEventListener('focus', this.docHandleFocus, true);
95
+ document.addEventListener('blur', this.docHandleBlur, true);
96
+ this.initializeJqueryWrapper(Tabs, 'tabs', 'M_Tabs');
97
+ this.initializeJqueryWrapper(Carousel, 'carousel', 'M_Carousel');
98
+ this.initializeJqueryWrapper(Autocomplete, 'autocomplete', 'M_Autocomplete');
99
+ this.initializeJqueryWrapper(Dropdown, 'dropdown', 'M_Dropdown');
100
+ this.initializeJqueryWrapper(FloatingActionButton, 'floatingActionButton', 'M_FloatingActionButton');
101
+ M.initializeJqueryWrapper(Collapsible, 'collapsible', 'M_Collapsible');
102
+ M.initializeJqueryWrapper(CharacterCounter, 'characterCounter', 'M_CharacterCounter');
103
+ M.initializeJqueryWrapper(Datepicker, 'datepicker', 'M_Datepicker');
104
+ M.initializeJqueryWrapper(FormSelect, 'formSelect', 'M_FormSelect');
105
+ M.initializeJqueryWrapper(Modal, 'modal', 'M_Modal');
106
+ M.initializeJqueryWrapper(Pushpin, 'pushpin', 'M_Pushpin');
107
+ M.initializeJqueryWrapper(Materialbox, 'materialbox', 'M_Materialbox');
108
+ M.initializeJqueryWrapper(Parallax, 'parallax', 'M_Parallax');
109
+ M.initializeJqueryWrapper(Slider, 'slider', 'M_Slider');
110
+ M.initializeJqueryWrapper(Timepicker, 'timepicker', 'M_Timepicker');
111
+ M.initializeJqueryWrapper(Tooltip, 'tooltip', 'M_Tooltip');
112
+ M.initializeJqueryWrapper(TapTarget, 'tapTarget', 'M_TapTarget');
113
+ M.initializeJqueryWrapper(Sidenav, 'sidenav', 'M_Sidenav');
114
+ M.initializeJqueryWrapper(ScrollSpy, 'scrollSpy', 'M_ScrollSpy');
115
+ M.initializeJqueryWrapper(Range, 'range', 'M_Range');
116
+ M.initializeJqueryWrapper(Chips, 'chips', 'M_Chips');
117
+ Cards.Init();
118
+ Forms.Init();
119
+ Chips.Init();
120
+ Waves.Init();
121
+ Range.Init();
122
+ }
123
+
124
+ //--- TODO: Remove!
125
+ static jQueryLoaded(): boolean {
126
+ return !!(<any>window).jQuery;
127
+ }
128
+ static initializeJqueryWrapper(plugin: any, pluginName: string, classRef: string) {
129
+ if (!this.jQueryLoaded())
130
+ return;
131
+ var jq = (<any>window).jQuery;
132
+
133
+ jq.fn[pluginName] = function(methodOrOptions) {
134
+ // Call plugin method if valid method name is passed in
135
+ if (plugin.prototype[methodOrOptions]) {
136
+ let params = Array.prototype.slice.call(arguments, 1);
137
+ // Getter methods
138
+ if (methodOrOptions.slice(0, 3) === 'get') {
139
+ let instance = this.first()[0][classRef];
140
+ return instance[methodOrOptions].apply(instance, params);
141
+ }
142
+ // Void methods
143
+ return this.each(function() {
144
+ let instance = this[classRef];
145
+ instance[methodOrOptions].apply(instance, params);
146
+ });
147
+ // Initialize plugin if options or no argument is passed in
148
+ } else if (typeof methodOrOptions === 'object' || !methodOrOptions) {
149
+ plugin.init(this, arguments[0]);
150
+ return this;
151
+ }
152
+ // Return error if an unrecognized method name is passed in
153
+ jq.error(`Method ${methodOrOptions} does not exist on jQuery.${pluginName}`);
154
+ };
155
+ }
156
+ //---
157
+
158
+ static AutoInit(context:Element = null) {
159
+ let root = !!context ? context : document.body;
160
+ let registry = {
161
+ Autocomplete: root.querySelectorAll('.autocomplete:not(.no-autoinit)'),
162
+ Carousel: root.querySelectorAll('.carousel:not(.no-autoinit)'),
163
+ Chips: root.querySelectorAll('.chips:not(.no-autoinit)'),
164
+ Collapsible: root.querySelectorAll('.collapsible:not(.no-autoinit)'),
165
+ Datepicker: root.querySelectorAll('.datepicker:not(.no-autoinit)'),
166
+ Dropdown: root.querySelectorAll('.dropdown-trigger:not(.no-autoinit)'),
167
+ Materialbox: root.querySelectorAll('.materialboxed:not(.no-autoinit)'),
168
+ Modal: root.querySelectorAll('.modal:not(.no-autoinit)'),
169
+ Parallax: root.querySelectorAll('.parallax:not(.no-autoinit)'),
170
+ Pushpin: root.querySelectorAll('.pushpin:not(.no-autoinit)'),
171
+ ScrollSpy: root.querySelectorAll('.scrollspy:not(.no-autoinit)'),
172
+ FormSelect: root.querySelectorAll('select:not(.no-autoinit)'),
173
+ Sidenav: root.querySelectorAll('.sidenav:not(.no-autoinit)'),
174
+ Tabs: root.querySelectorAll('.tabs:not(.no-autoinit)'),
175
+ TapTarget: root.querySelectorAll('.tap-target:not(.no-autoinit)'),
176
+ Timepicker: root.querySelectorAll('.timepicker:not(.no-autoinit)'),
177
+ Tooltip: root.querySelectorAll('.tooltipped:not(.no-autoinit)'),
178
+ FloatingActionButton: root.querySelectorAll('.fixed-action-btn:not(.no-autoinit)'),
179
+ };
180
+ M.Autocomplete.init(registry.Autocomplete, null);
181
+ M.Carousel.init(registry.Carousel, null);
182
+ M.Chips.init(registry.Chips, null);
183
+ M.Collapsible.init(registry.Collapsible, null);
184
+ M.Datepicker.init(registry.Datepicker, null);
185
+ M.Dropdown.init(registry.Dropdown, null);
186
+ M.Materialbox.init(registry.Materialbox, null);
187
+ M.Modal.init(registry.Modal, null);
188
+ M.Parallax.init(registry.Parallax, null);
189
+ M.Pushpin.init(registry.Pushpin, null);
190
+ M.ScrollSpy.init(registry.ScrollSpy, null);
191
+ M.FormSelect.init(registry.FormSelect, null);
192
+ M.Sidenav.init(registry.Sidenav, null);
193
+ M.Tabs.init(registry.Tabs, null);
194
+ M.TapTarget.init(registry.TapTarget, null);
195
+ M.Timepicker.init(registry.Timepicker, null);
196
+ M.Tooltip.init(registry.Tooltip, null);
197
+ M.FloatingActionButton.init(registry.FloatingActionButton, null);
198
+ }
199
+
200
+ static objectSelectorString(obj: any): string {
201
+ let tagStr = obj.prop('tagName') || '';
202
+ let idStr = obj.attr('id') || '';
203
+ let classStr = obj.attr('class') || '';
204
+ return (tagStr + idStr + classStr).replace(/\s/g, '');
205
+ }
206
+
207
+ static guid(): string {
208
+ function s4():string {
209
+ return Math.floor((1 + Math.random()) * 0x10000)
210
+ .toString(16)
211
+ .substring(1);
212
+ }
213
+ return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
214
+ }
215
+
216
+ static checkWithinContainer(container: Element, bounding: Bounding, offset: number): Edges {
217
+ let edges = {
218
+ top: false,
219
+ right: false,
220
+ bottom: false,
221
+ left: false
222
+ };
223
+
224
+ let containerRect = container.getBoundingClientRect();
225
+ // If body element is smaller than viewport, use viewport height instead.
226
+ let containerBottom =
227
+ container === document.body
228
+ ? Math.max(containerRect.bottom, window.innerHeight)
229
+ : containerRect.bottom;
230
+
231
+ let scrollLeft = container.scrollLeft;
232
+ let scrollTop = container.scrollTop;
233
+
234
+ let scrolledX = bounding.left - scrollLeft;
235
+ let scrolledY = bounding.top - scrollTop;
236
+
237
+ // Check for container and viewport for each edge
238
+ if (scrolledX < containerRect.left + offset || scrolledX < offset) {
239
+ edges.left = true;
240
+ }
241
+
242
+ if (
243
+ scrolledX + bounding.width > containerRect.right - offset ||
244
+ scrolledX + bounding.width > window.innerWidth - offset
245
+ ) {
246
+ edges.right = true;
247
+ }
248
+
249
+ if (scrolledY < containerRect.top + offset || scrolledY < offset) {
250
+ edges.top = true;
251
+ }
252
+
253
+ if (
254
+ scrolledY + bounding.height > containerBottom - offset ||
255
+ scrolledY + bounding.height > window.innerHeight - offset
256
+ ) {
257
+ edges.bottom = true;
258
+ }
259
+
260
+ return edges;
261
+ }
262
+
263
+ static checkPossibleAlignments(el, container, bounding, offset) {
264
+ let canAlign = {
265
+ top: true,
266
+ right: true,
267
+ bottom: true,
268
+ left: true,
269
+ spaceOnTop: null,
270
+ spaceOnRight: null,
271
+ spaceOnBottom: null,
272
+ spaceOnLeft: null
273
+ };
274
+
275
+ let containerAllowsOverflow = getComputedStyle(container).overflow === 'visible';
276
+ let containerRect = container.getBoundingClientRect();
277
+ let containerHeight = Math.min(containerRect.height, window.innerHeight);
278
+ let containerWidth = Math.min(containerRect.width, window.innerWidth);
279
+ let elOffsetRect = el.getBoundingClientRect();
280
+
281
+ let scrollLeft = container.scrollLeft;
282
+ let scrollTop = container.scrollTop;
283
+
284
+ let scrolledX = bounding.left - scrollLeft;
285
+ let scrolledYTopEdge = bounding.top - scrollTop;
286
+ let scrolledYBottomEdge = bounding.top + elOffsetRect.height - scrollTop;
287
+
288
+ // Check for container and viewport for left
289
+ canAlign.spaceOnRight = !containerAllowsOverflow
290
+ ? containerWidth - (scrolledX + bounding.width)
291
+ : window.innerWidth - (elOffsetRect.left + bounding.width);
292
+ if (canAlign.spaceOnRight < 0) {
293
+ canAlign.left = false;
294
+ }
295
+
296
+ // Check for container and viewport for Right
297
+ canAlign.spaceOnLeft = !containerAllowsOverflow
298
+ ? scrolledX - bounding.width + elOffsetRect.width
299
+ : elOffsetRect.right - bounding.width;
300
+ if (canAlign.spaceOnLeft < 0) {
301
+ canAlign.right = false;
302
+ }
303
+
304
+ // Check for container and viewport for Top
305
+ canAlign.spaceOnBottom = !containerAllowsOverflow
306
+ ? containerHeight - (scrolledYTopEdge + bounding.height + offset)
307
+ : window.innerHeight - (elOffsetRect.top + bounding.height + offset);
308
+ if (canAlign.spaceOnBottom < 0) {
309
+ canAlign.top = false;
310
+ }
311
+
312
+ // Check for container and viewport for Bottom
313
+ canAlign.spaceOnTop = !containerAllowsOverflow
314
+ ? scrolledYBottomEdge - (bounding.height - offset)
315
+ : elOffsetRect.bottom - (bounding.height + offset);
316
+ if (canAlign.spaceOnTop < 0) {
317
+ canAlign.bottom = false;
318
+ }
319
+
320
+ return canAlign;
321
+ }
322
+
323
+ static getOverflowParent(element) {
324
+ if (element == null) {
325
+ return null;
326
+ }
327
+ if (element === document.body || getComputedStyle(element).overflow !== 'visible') {
328
+ return element;
329
+ }
330
+ return this.getOverflowParent(element.parentElement);
331
+ }
332
+
333
+ static getIdFromTrigger(trigger: Element): string {
334
+ let id = trigger.getAttribute('data-target');
335
+ if (!id) {
336
+ id = trigger.getAttribute('href');
337
+ if (id) {
338
+ id = id.slice(1);
339
+ } else {
340
+ id = '';
341
+ }
342
+ }
343
+ return id;
344
+ }
345
+
346
+ static getDocumentScrollTop(): number {
347
+ return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
348
+ };
349
+
350
+ static getDocumentScrollLeft(): number {
351
+ return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
352
+ }
353
+
354
+ public static throttle(func, wait, options = null) {
355
+ let context, args, result;
356
+ let timeout = null;
357
+ let previous = 0;
358
+ options || (options = {});
359
+ let later = function() {
360
+ previous = options.leading === false ? 0 : new Date().getTime();
361
+ timeout = null;
362
+ result = func.apply(context, args);
363
+ context = args = null;
364
+ };
365
+ return function() {
366
+ let now = new Date().getTime();
367
+ if (!previous && options.leading === false) previous = now;
368
+ let remaining = wait - (now - previous);
369
+ context = this;
370
+ args = arguments;
371
+ if (remaining <= 0) {
372
+ clearTimeout(timeout);
373
+ timeout = null;
374
+ previous = now;
375
+ result = func.apply(context, args);
376
+ context = args = null;
377
+ } else if (!timeout && options.trailing !== false) {
378
+ timeout = setTimeout(later, remaining);
379
+ }
380
+ return result;
381
+ };
382
+ }
383
+ }
384
+
385
+ export default M;