Skip to content

Commit c6b8eaa

Browse files
feat(utils): global utilities
- Finished removing native jQuery support; - Migrated global constants and utilitary functions to "Utils" module; - Added type definitions and docs to "Utils" module; - Exposed "Utils" module in global namespace ("M"); - Components no longer need to import global namespace; - Removed unnecessary throttle wrapper function on components; - Updated type definition for toast function + added docs; - Fix touch event when target does not have a close carousel item; - Fixed incorrect event instance check; - Fixed type definitions using "Boolean" object as type.
2 parents 32ad112 + 4131b77 commit c6b8eaa

22 files changed

+393
-399
lines changed

src/autocomplete.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { M } from "./global";
1+
import { Utils } from "./utils";
22
import { Dropdown, DropdownOptions } from "./dropdown";
33
import { Component, BaseOptions, InitElements } from "./component";
44

@@ -214,7 +214,7 @@ export class Autocomplete extends Component<AutocompleteOptions> {
214214
_setupDropdown() {
215215
this.container = document.createElement('ul');
216216
this.container.style.maxHeight = this.options.maxDropDownHeight;
217-
this.container.id = `autocomplete-options-${M.guid()}`;
217+
this.container.id = `autocomplete-options-${Utils.guid()}`;
218218
this.container.classList.add('autocomplete-content', 'dropdown-content');
219219
this.el.setAttribute('data-target', this.container.id);
220220

@@ -236,7 +236,7 @@ export class Autocomplete extends Component<AutocompleteOptions> {
236236
if (userOnItemClick && typeof userOnItemClick === 'function')
237237
userOnItemClick.call(this.dropdown, this.el);
238238
};
239-
this.dropdown = M.Dropdown.init(this.el, dropdownOptions);
239+
this.dropdown = Dropdown.init(this.el, dropdownOptions);
240240

241241
// ! Workaround for Label: move label up again
242242
// TODO: Just use PopperJS in future!
@@ -271,10 +271,10 @@ export class Autocomplete extends Component<AutocompleteOptions> {
271271
this.count = 0;
272272
const actualValue = this.el.value.toLowerCase();
273273
// Don't capture enter or arrow key usage.
274-
if (M.keys.ENTER.includes(e.key) || M.keys.ARROW_UP.includes(e.key) || M.keys.ARROW_DOWN.includes(e.key)) return;
274+
if (Utils.keys.ENTER.includes(e.key) || Utils.keys.ARROW_UP.includes(e.key) || Utils.keys.ARROW_DOWN.includes(e.key)) return;
275275
// Check if the input isn't empty
276276
// Check if focus triggered by tab
277-
if (this.oldVal !== actualValue && (M.tabPressed || e.type !== 'focus')) {
277+
if (this.oldVal !== actualValue && (Utils.tabPressed || e.type !== 'focus')) {
278278
this.open();
279279
}
280280
// Value has changed!
@@ -295,7 +295,7 @@ export class Autocomplete extends Component<AutocompleteOptions> {
295295
// Arrow keys and enter key usage
296296
const numItems = this.container.querySelectorAll('li').length;
297297
// select element on Enter
298-
if (M.keys.ENTER.includes(e.key) && this.activeIndex >= 0) {
298+
if (Utils.keys.ENTER.includes(e.key) && this.activeIndex >= 0) {
299299
const liElement = this.container.querySelectorAll('li')[this.activeIndex];
300300
if (liElement) {
301301
this.selectOption(liElement.getAttribute('data-id'));
@@ -304,10 +304,10 @@ export class Autocomplete extends Component<AutocompleteOptions> {
304304
return;
305305
}
306306
// Capture up and down key
307-
if (M.keys.ARROW_UP.includes(e.key) || M.keys.ARROW_DOWN.includes(e.key)) {
307+
if (Utils.keys.ARROW_UP.includes(e.key) || Utils.keys.ARROW_DOWN.includes(e.key)) {
308308
e.preventDefault();
309-
if (M.keys.ARROW_UP.includes(e.key) && this.activeIndex > 0) this.activeIndex--;
310-
if (M.keys.ARROW_DOWN.includes(e.key) && this.activeIndex < numItems - 1) this.activeIndex++;
309+
if (Utils.keys.ARROW_UP.includes(e.key) && this.activeIndex > 0) this.activeIndex--;
310+
if (Utils.keys.ARROW_DOWN.includes(e.key) && this.activeIndex < numItems - 1) this.activeIndex++;
311311
this.$active?.classList.remove('active');
312312
if (this.activeIndex >= 0) {
313313
this.$active = this.container.querySelectorAll('li')[this.activeIndex];

src/carousel.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { M } from "./global";
1+
import { Utils } from "./utils";
22
import { Component, BaseOptions, InitElements } from "./component";
33

44
export interface CarouselOptions extends BaseOptions{
@@ -236,7 +236,7 @@ export class Carousel extends Component<CarouselOptions> {
236236
window.removeEventListener('resize', this._handleThrottledResize);
237237
}
238238

239-
_handleThrottledResize = (() => M.throttle(function(){ this._handleResize(); }, 200, null).bind(this))();
239+
_handleThrottledResize: () => void = Utils.throttle(function(){ this._handleResize(); }, 200, null).bind(this);
240240

241241
_handleCarouselTap = (e: MouseEvent | TouchEvent) => {
242242
// Fixes firefox draggable image bug
@@ -328,6 +328,7 @@ export class Carousel extends Component<CarouselOptions> {
328328
}
329329
else if (!this.options.fullWidth) {
330330
const clickedElem = (<HTMLElement>e.target).closest('.carousel-item');
331+
if (!clickedElem) return;
331332
const clickedIndex = [...clickedElem.parentNode.children].indexOf(clickedElem);
332333
const diff = this._wrap(this.center) - clickedIndex;
333334
// Disable clicks if carousel was shifted by click
@@ -407,17 +408,17 @@ export class Carousel extends Component<CarouselOptions> {
407408

408409
_xpos(e: MouseEvent | TouchEvent) {
409410
// touch event
410-
if (e instanceof TouchEvent && e.targetTouches.length >= 1) {
411-
return e.targetTouches[0].clientX;
411+
if (e.type.startsWith("touch") && (e as TouchEvent).targetTouches.length >= 1) {
412+
return (e as TouchEvent).targetTouches[0].clientX;
412413
}
413414
// mouse event
414415
return (e as MouseEvent).clientX;
415416
}
416417

417418
_ypos(e: MouseEvent | TouchEvent) {
418419
// touch event
419-
if (e instanceof TouchEvent && e.targetTouches.length >= 1) {
420-
return e.targetTouches[0].clientY;
420+
if (e.type.startsWith("touch") && (e as TouchEvent).targetTouches.length >= 1) {
421+
return (e as TouchEvent).targetTouches[0].clientY;
421422
}
422423
// mouse event
423424
return (e as MouseEvent).clientY;

src/chips.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { M } from "./global";
1+
import { Utils } from "./utils";
22
import { Autocomplete, AutocompleteOptions } from "./autocomplete";
33
import { Component, BaseOptions, InitElements } from "./component";
44

@@ -117,7 +117,7 @@ export class Chips extends Component<ChipsOptions> {
117117

118118
// Set input id
119119
if (!this._input.getAttribute('id'))
120-
this._input.setAttribute('id', M.guid());
120+
this._input.setAttribute('id', Utils.guid());
121121

122122
// Render initial chips
123123
if (this.options.data.length) {
@@ -221,7 +221,7 @@ export class Chips extends Component<ChipsOptions> {
221221

222222
const currChips: Chips = (chips as any).M_Chips;
223223

224-
if (M.keys.BACKSPACE.includes(e.key) || M.keys.DELETE.includes(e.key)) {
224+
if (Utils.keys.BACKSPACE.includes(e.key) || Utils.keys.DELETE.includes(e.key)) {
225225
e.preventDefault();
226226
let selectIndex = currChips.chipsData.length;
227227
if (currChips._selectedChip) {
@@ -236,14 +236,14 @@ export class Chips extends Component<ChipsOptions> {
236236
else
237237
currChips._input.focus();
238238
}
239-
else if (M.keys.ARROW_LEFT.includes(e.key)) {
239+
else if (Utils.keys.ARROW_LEFT.includes(e.key)) {
240240
if (currChips._selectedChip) {
241241
const selectIndex = gGetIndex(currChips._selectedChip) - 1;
242242
if (selectIndex < 0) return;
243243
currChips.selectChip(selectIndex);
244244
}
245245
}
246-
else if (M.keys.ARROW_RIGHT.includes(e.key)) {
246+
else if (Utils.keys.ARROW_RIGHT.includes(e.key)) {
247247
if (currChips._selectedChip) {
248248
const selectIndex = gGetIndex(currChips._selectedChip) + 1;
249249
if (selectIndex >= currChips.chipsData.length)
@@ -276,7 +276,7 @@ export class Chips extends Component<ChipsOptions> {
276276

277277
_handleInputKeydown = (e: KeyboardEvent) => {
278278
Chips._keydown = true;
279-
if (M.keys.ENTER.includes(e.key)) {
279+
if (Utils.keys.ENTER.includes(e.key)) {
280280
// Override enter if autocompleting.
281281
if (this.hasAutocomplete && this.autocomplete && this.autocomplete.isOpen) {
282282
return;
@@ -288,7 +288,7 @@ export class Chips extends Component<ChipsOptions> {
288288
this._input.value = '';
289289
}
290290
else if (
291-
(M.keys.BACKSPACE.includes(e.key) || M.keys.ARROW_LEFT.includes(e.key)) &&
291+
(Utils.keys.BACKSPACE.includes(e.key) || Utils.keys.ARROW_LEFT.includes(e.key)) &&
292292
this._input.value === '' &&
293293
this.chipsData.length
294294
) {

src/collapsible.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import anim from "animejs";
22

3-
import { M } from "./global";
3+
import { Utils } from "./utils";
44
import { Component, BaseOptions, InitElements } from "./component";
55

66
export interface CollapsibleOptions extends BaseOptions {
@@ -138,7 +138,7 @@ export class Collapsible extends Component<CollapsibleOptions> {
138138
}
139139

140140
_handleCollapsibleKeydown = (e: KeyboardEvent) => {
141-
if (M.keys.ENTER.includes(e.key)) {
141+
if (Utils.keys.ENTER.includes(e.key)) {
142142
this._handleCollapsibleClick(e);
143143
}
144144
}

src/datepicker.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { M } from "./global";
21
import { Modal } from "./modal";
2+
import { Utils } from "./utils";
33
import { FormSelect } from "./select";
44
import { BaseOptions, Component, InitElements, I18nOptions } from "./component";
55

@@ -276,7 +276,7 @@ export class Datepicker extends Component<DatepickerOptions> {
276276
if (this.options.minDate) this.options.minDate.setHours(0, 0, 0, 0);
277277
if (this.options.maxDate) this.options.maxDate.setHours(0, 0, 0, 0);
278278

279-
this.id = M.guid();
279+
this.id = Utils.guid();
280280

281281
this._setupVariables();
282282
this._insertHTMLIntoDOM();
@@ -930,7 +930,7 @@ export class Datepicker extends Component<DatepickerOptions> {
930930
}
931931

932932
_handleInputKeydown = (e: KeyboardEvent) => {
933-
if (M.keys.ENTER.includes(e.key)) {
933+
if (Utils.keys.ENTER.includes(e.key)) {
934934
e.preventDefault();
935935
this.open();
936936
}

src/dropdown.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import anim from "animejs";
22

3-
import { M } from "./global";
3+
import { Utils } from "./utils";
44
import { Component, BaseOptions, InitElements, Openable } from "./component";
55

66
export interface DropdownOptions extends BaseOptions {
@@ -114,7 +114,7 @@ export class Dropdown extends Component<DropdownOptions> implements Openable {
114114
(this.el as any).M_Dropdown = this;
115115

116116
Dropdown._dropdowns.push(this);
117-
this.id = M.getIdFromTrigger(el);
117+
this.id = Utils.getIdFromTrigger(el);
118118
this.dropdownEl = document.getElementById(this.id);
119119

120120
this.options = {
@@ -264,7 +264,7 @@ export class Dropdown extends Component<DropdownOptions> implements Openable {
264264

265265
_handleTriggerKeydown = (e: KeyboardEvent) => {
266266
// ARROW DOWN OR ENTER WHEN SELECT IS CLOSED - open Dropdown
267-
const arrowDownOrEnter = M.keys.ARROW_DOWN.includes(e.key) || M.keys.ENTER.includes(e.key);
267+
const arrowDownOrEnter = Utils.keys.ARROW_DOWN.includes(e.key) || Utils.keys.ENTER.includes(e.key);
268268
if (arrowDownOrEnter && !this.isOpen) {
269269
e.preventDefault();
270270
this.open();
@@ -287,15 +287,15 @@ export class Dropdown extends Component<DropdownOptions> implements Openable {
287287
}
288288

289289
_handleDropdownKeydown = (e: KeyboardEvent) => {
290-
const arrowUpOrDown = M.keys.ARROW_DOWN.includes(e.key) || M.keys.ARROW_UP.includes(e.key);
291-
if (M.keys.TAB.includes(e.key)) {
290+
const arrowUpOrDown = Utils.keys.ARROW_DOWN.includes(e.key) || Utils.keys.ARROW_UP.includes(e.key);
291+
if (Utils.keys.TAB.includes(e.key)) {
292292
e.preventDefault();
293293
this.close();
294294
}
295295
// Navigate down dropdown list
296296
else if (arrowUpOrDown && this.isOpen) {
297297
e.preventDefault();
298-
const direction = M.keys.ARROW_DOWN.includes(e.key) ? 1 : -1;
298+
const direction = Utils.keys.ARROW_DOWN.includes(e.key) ? 1 : -1;
299299
let newFocusedIndex = this.focusedIndex;
300300
let hasFoundNewIndex = false;
301301
do {
@@ -318,7 +318,7 @@ export class Dropdown extends Component<DropdownOptions> implements Openable {
318318
}
319319
}
320320
// ENTER selects choice on focused item
321-
else if (M.keys.ENTER.includes(e.key) && this.isOpen) {
321+
else if (Utils.keys.ENTER.includes(e.key) && this.isOpen) {
322322
// Search for <a> and <button>
323323
const focusedElement = this.dropdownEl.children[this.focusedIndex];
324324
const activatableElement = <HTMLElement>focusedElement.querySelector('a, button');
@@ -333,15 +333,15 @@ export class Dropdown extends Component<DropdownOptions> implements Openable {
333333
}
334334
}
335335
// Close dropdown on ESC
336-
else if (M.keys.ESC.includes(e.key) && this.isOpen) {
336+
else if (Utils.keys.ESC.includes(e.key) && this.isOpen) {
337337
e.preventDefault();
338338
this.close();
339339
}
340340

341341
// CASE WHEN USER TYPE LTTERS
342342
const keyText = e.key.toLowerCase();
343343
const isLetter = /[a-zA-Z0-9-_]/.test(keyText);
344-
const specialKeys = [...M.keys.ARROW_DOWN, ...M.keys.ARROW_UP, ...M.keys.ENTER, ...M.keys.ESC, ...M.keys.TAB];
344+
const specialKeys = [...Utils.keys.ARROW_DOWN, ...Utils.keys.ARROW_UP, ...Utils.keys.ENTER, ...Utils.keys.ESC, ...Utils.keys.TAB];
345345
if (isLetter && !specialKeys.includes(e.key)) {
346346
this.filterQuery.push(keyText);
347347
const string = this.filterQuery.join('');
@@ -430,7 +430,7 @@ export class Dropdown extends Component<DropdownOptions> implements Openable {
430430
width: idealWidth
431431
};
432432

433-
const alignments = M.checkPossibleAlignments(
433+
const alignments = Utils.checkPossibleAlignments(
434434
this.el,
435435
closestOverflowParent,
436436
dropdownBounds,

src/edges.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export class Edges {
2-
public top: Boolean; // If the top edge was exceeded
3-
public right: Boolean; // If the right edge was exceeded
4-
public bottom: Boolean; // If the bottom edge was exceeded
5-
public left: Boolean; // If the left edge was exceeded
2+
public top: boolean; // If the top edge was exceeded
3+
public right: boolean; // If the right edge was exceeded
4+
public bottom: boolean; // If the bottom edge was exceeded
5+
public left: boolean; // If the left edge was exceeded
66
}

src/forms.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { M } from "./global";
1+
import { Utils } from "./utils";
22

33
export class Forms {
44

@@ -81,7 +81,7 @@ export class Forms {
8181
// Radio and Checkbox focus class
8282
if (target instanceof HTMLInputElement && ['radio','checkbox'].includes(target.type)) {
8383
// TAB, check if tabbing to radio or checkbox.
84-
if (M.keys.TAB.includes(e.key)) {
84+
if (Utils.keys.TAB.includes(e.key)) {
8585
target.classList.add('tabbed');
8686
target.addEventListener('blur', e => target.classList.remove('tabbed'), {once: true});
8787
}

0 commit comments

Comments
 (0)