Skip to content

Commit c23838b

Browse files
Use type-check utils instead of typeof (#333)
* Use type-check utils instead of typeof * Remove double negation
1 parent 2040ab1 commit c23838b

File tree

8 files changed

+103
-54
lines changed

8 files changed

+103
-54
lines changed

src/js/constraint.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { updateClasses } from './utils/classes';
22
import { defer } from './utils/deferred';
33
import { extend } from './utils/general';
44
import { getBounds } from './utils/bounds';
5+
import { isString, isUndefined } from './utils/type-check';
56

67
const BOUNDS_FORMAT = ['left', 'top', 'right', 'bottom'];
78

@@ -16,7 +17,7 @@ function getBoundingRect(tether, to) {
1617
to = to.documentElement;
1718
}
1819

19-
if (typeof to.nodeType !== 'undefined') {
20+
if (!isUndefined(to.nodeType)) {
2021
const node = to;
2122
const size = getBounds(to);
2223
const pos = size;
@@ -56,7 +57,7 @@ export default {
5657
return getBounds(this.element);
5758
});
5859

59-
if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') {
60+
if (width === 0 && height === 0 && !isUndefined(this.lastSize)) {
6061
// Handle the item getting hidden as a result of our positioning without glitching
6162
// the classes in and out
6263
({ width, height } = this.lastSize);
@@ -94,7 +95,7 @@ export default {
9495
this.options.constraints.forEach((constraint) => {
9596
let { to, attachment, pin } = constraint;
9697

97-
if (typeof attachment === 'undefined') {
98+
if (isUndefined(attachment)) {
9899
attachment = '';
99100
}
100101

@@ -256,7 +257,7 @@ export default {
256257
}
257258
}
258259

259-
if (typeof pin === 'string') {
260+
if (isString(pin)) {
260261
pin = pin.split(',').map((p) => p.trim());
261262
} else if (pin === true) {
262263
pin = ['top', 'left', 'right', 'bottom'];
@@ -305,7 +306,7 @@ export default {
305306

306307
if (pinned.length) {
307308
let pinnedClass;
308-
if (typeof this.options.pinnedClass !== 'undefined') {
309+
if (!isUndefined(this.options.pinnedClass)) {
309310
pinnedClass = this.options.pinnedClass;
310311
} else {
311312
pinnedClass = this.getClass('pinned');
@@ -319,7 +320,7 @@ export default {
319320

320321
if (oob.length) {
321322
let oobClass;
322-
if (typeof this.options.outOfBoundsClass !== 'undefined') {
323+
if (!isUndefined(this.options.outOfBoundsClass)) {
323324
oobClass = this.options.outOfBoundsClass;
324325
} else {
325326
oobClass = this.getClass('out-of-bounds');

src/js/evented.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import { isUndefined } from './utils/type-check';
2+
13
export class Evented {
24
on(event, handler, ctx, once = false) {
3-
if (typeof this.bindings === 'undefined') {
5+
if (isUndefined(this.bindings)) {
46
this.bindings = {};
57
}
6-
if (typeof this.bindings[event] === 'undefined') {
8+
if (isUndefined(this.bindings[event])) {
79
this.bindings[event] = [];
810
}
911
this.bindings[event].push({ handler, ctx, once });
@@ -16,12 +18,12 @@ export class Evented {
1618
}
1719

1820
off(event, handler) {
19-
if (typeof this.bindings === 'undefined' ||
20-
typeof this.bindings[event] === 'undefined') {
21+
if (isUndefined(this.bindings) ||
22+
isUndefined(this.bindings[event])) {
2123
return this;
2224
}
2325

24-
if (typeof handler === 'undefined') {
26+
if (isUndefined(handler)) {
2527
delete this.bindings[event];
2628
} else {
2729
let i = 0;
@@ -38,13 +40,13 @@ export class Evented {
3840
}
3941

4042
trigger(event, ...args) {
41-
if (typeof this.bindings !== 'undefined' && this.bindings[event]) {
43+
if (!isUndefined(this.bindings) && this.bindings[event]) {
4244
let i = 0;
4345
while (i < this.bindings[event].length) {
4446
const { handler, ctx, once } = this.bindings[event][i];
4547

4648
let context = ctx;
47-
if (typeof context === 'undefined') {
49+
if (isUndefined(context)) {
4850
context = this;
4951
}
5052

src/js/shift.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1+
import { isFunction, isString } from './utils/type-check';
2+
13
export default {
24
position({ top, left }) {
35
if (!this.options.shift) {
46
return;
57
}
68

79
let { shift } = this.options;
8-
if (typeof shift === 'function') {
10+
if (isFunction(shift)) {
911
shift = shift.call(this, { top, left });
1012
}
1113

1214
let shiftTop, shiftLeft;
13-
if (typeof shift === 'string') {
15+
if (isString(shift)) {
1416
shift = shift.split(' ');
1517
shift[1] = shift[1] || shift[0];
1618

src/js/tether.js

+29-29
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { extend, getScrollBarSize } from './utils/general';
1212
import { addOffset, attachmentToOffset, autoToFixedAttachment, offsetToPx, parseTopLeft } from './utils/offset';
1313
import { getBounds, removeUtilElements } from './utils/bounds';
1414
import { getOffsetParent, getScrollParents } from './utils/parents';
15+
import { isNumber, isObject, isString, isUndefined } from './utils/type-check';
1516

1617
const TetherBase = { modules: [Constraint, Abutment, Shift] };
1718

@@ -26,7 +27,7 @@ function within(a, b, diff = 1) {
2627
}
2728

2829
const transformKey = (() => {
29-
if (typeof document === 'undefined') {
30+
if (isUndefined(document)) {
3031
return '';
3132
}
3233
const el = document.createElement('div');
@@ -59,7 +60,7 @@ function now() {
5960
let pendingTimeout = null;
6061

6162
const tick = () => {
62-
if (typeof lastDuration !== 'undefined' && lastDuration > 16) {
63+
if (!isUndefined(lastDuration) && lastDuration > 16) {
6364
// We voluntarily throttle ourselves if we can't manage 60fps
6465
lastDuration = Math.min(lastDuration - 16, 250);
6566

@@ -68,7 +69,7 @@ function now() {
6869
return;
6970
}
7071

71-
if (typeof lastCall !== 'undefined' && (now() - lastCall) < 10) {
72+
if (!isUndefined(lastCall) && (now() - lastCall) < 10) {
7273
// Some browsers call events a little too frequently, refuse to run more than is reasonable
7374
return;
7475
}
@@ -83,7 +84,7 @@ function now() {
8384
lastDuration = now() - lastCall;
8485
};
8586

86-
if (typeof window !== 'undefined' && typeof window.addEventListener !== 'undefined') {
87+
if (!isUndefined(window) && !isUndefined(window.addEventListener)) {
8788
['resize', 'scroll', 'touchmove'].forEach((event) => {
8889
window.addEventListener(event, tick);
8990
});
@@ -102,7 +103,7 @@ class TetherClass extends Evented {
102103
this.setOptions(options, false);
103104

104105
TetherBase.modules.forEach((module) => {
105-
if (typeof module.initialize !== 'undefined') {
106+
if (!isUndefined(module.initialize)) {
106107
module.initialize.call(this);
107108
}
108109
});
@@ -112,7 +113,7 @@ class TetherClass extends Evented {
112113

113114
getClass(key = '') {
114115
const { classes } = this.options;
115-
if (typeof classes !== 'undefined' && typeof classes[key] !== 'undefined') {
116+
if (!isUndefined(classes) && !isUndefined(classes[key])) {
116117
if (classes[key] === false) {
117118
return '';
118119
}
@@ -148,13 +149,13 @@ class TetherClass extends Evented {
148149
}
149150

150151
['element', 'target'].forEach((key) => {
151-
if (typeof this[key] === 'undefined') {
152+
if (isUndefined(this[key])) {
152153
throw new Error('Tether Error: Both element and target must be defined');
153154
}
154155

155-
if (typeof this[key].jquery !== 'undefined') {
156+
if (!isUndefined(this[key].jquery)) {
156157
this[key] = this[key][0];
157-
} else if (typeof this[key] === 'string') {
158+
} else if (isString(this[key])) {
158159
this[key] = document.querySelector(this[key]);
159160
}
160161
});
@@ -170,7 +171,7 @@ class TetherClass extends Evented {
170171
this.offset = parseTopLeft(this.options.offset);
171172
this.targetOffset = parseTopLeft(this.options.targetOffset);
172173

173-
if (typeof this.scrollParents !== 'undefined') {
174+
if (!isUndefined(this.scrollParents)) {
174175
this.disable();
175176
}
176177

@@ -186,7 +187,7 @@ class TetherClass extends Evented {
186187
}
187188

188189
getTargetBounds() {
189-
if (typeof this.targetModifier !== 'undefined') {
190+
if (!isUndefined(this.targetModifier)) {
190191
if (this.targetModifier === 'visible') {
191192
if (this.target === document.body) {
192193
return { top: pageYOffset, left: pageXOffset, height: innerHeight, width: innerWidth };
@@ -286,11 +287,11 @@ class TetherClass extends Evented {
286287
cache(k, getter) {
287288
// More than one module will often need the same DOM info, so
288289
// we keep a cache which is cleared on each position call
289-
if (typeof this._cache === 'undefined') {
290+
if (isUndefined(this._cache)) {
290291
this._cache = {};
291292
}
292293

293-
if (typeof this._cache[k] === 'undefined') {
294+
if (isUndefined(this._cache[k])) {
294295
this._cache[k] = getter.call(this);
295296
}
296297

@@ -320,7 +321,7 @@ class TetherClass extends Evented {
320321
removeClass(this.element, this.getClass('enabled'));
321322
this.enabled = false;
322323

323-
if (typeof this.scrollParents !== 'undefined') {
324+
if (!isUndefined(this.scrollParents)) {
324325
this.scrollParents.forEach((parent) => {
325326
parent.removeEventListener('scroll', this.position);
326327
});
@@ -349,14 +350,14 @@ class TetherClass extends Evented {
349350
targetAttach = targetAttach || this.targetAttachment;
350351
const sides = ['left', 'top', 'bottom', 'right', 'middle', 'center'];
351352

352-
if (typeof this._addAttachClasses !== 'undefined' && this._addAttachClasses.length) {
353+
if (!isUndefined(this._addAttachClasses) && this._addAttachClasses.length) {
353354
// updateAttachClasses can be called more than once in a position call, so
354355
// we need to clean up after ourselves such that when the last defer gets
355356
// ran it doesn't add any extra classes from previous calls.
356357
this._addAttachClasses.splice(0, this._addAttachClasses.length);
357358
}
358359

359-
if (typeof this._addAttachClasses === 'undefined') {
360+
if (isUndefined(this._addAttachClasses)) {
360361
this._addAttachClasses = [];
361362
}
362363
this.add = this._addAttachClasses;
@@ -381,7 +382,7 @@ class TetherClass extends Evented {
381382
});
382383

383384
defer(() => {
384-
if (!(typeof this._addAttachClasses !== 'undefined')) {
385+
if (isUndefined(this._addAttachClasses)) {
385386
return;
386387
}
387388

@@ -415,7 +416,7 @@ class TetherClass extends Evented {
415416

416417
let { width, height } = elementPos;
417418

418-
if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') {
419+
if (width === 0 && height === 0 && !isUndefined(this.lastSize)) {
419420
// We cache the height and width to make it possible to position elements that are
420421
// getting hidden.
421422
({ width, height } = this.lastSize);
@@ -461,7 +462,7 @@ class TetherClass extends Evented {
461462

462463
if (ret === false) {
463464
return false;
464-
} else if (typeof ret === 'undefined' || typeof ret !== 'object') {
465+
} else if (isUndefined(ret) || !isObject(ret)) {
465466
continue;
466467
} else {
467468
({ top, left } = ret);
@@ -509,9 +510,9 @@ class TetherClass extends Evented {
509510
next.page.right = doc.body.scrollWidth - left - width;
510511
}
511512

512-
if (typeof this.options.optimizations !== 'undefined' &&
513+
if (!isUndefined(this.options.optimizations) &&
513514
this.options.optimizations.moveElement !== false &&
514-
!(typeof this.targetModifier !== 'undefined')) {
515+
isUndefined(this.targetModifier)) {
515516
const offsetParent = this.cache('target-offsetparent', () => getOffsetParent(this.target));
516517
const offsetPosition = this.cache('target-offsetparent-bounds', () => getBounds(offsetParent));
517518
const offsetParentStyle = getComputedStyle(offsetParent);
@@ -560,7 +561,7 @@ class TetherClass extends Evented {
560561

561562
// THE ISSUE
562563
move(pos) {
563-
if (!(typeof this.element.parentNode !== 'undefined')) {
564+
if (isUndefined(this.element.parentNode)) {
564565
return;
565566
}
566567

@@ -574,7 +575,7 @@ class TetherClass extends Evented {
574575

575576
for (let i = 0; i < this.history.length; ++i) {
576577
const point = this.history[i];
577-
if (typeof point[type] !== 'undefined' &&
578+
if (!isUndefined(point[type]) &&
578579
!within(point[type][key], pos[type][key])) {
579580
found = true;
580581
break;
@@ -591,7 +592,7 @@ class TetherClass extends Evented {
591592
let css = { top: '', left: '', right: '', bottom: '' };
592593

593594
const transcribe = (_same, _pos) => {
594-
const hasOptimizations = typeof this.options.optimizations !== 'undefined';
595+
const hasOptimizations = !isUndefined(this.options.optimizations);
595596
const gpu = hasOptimizations ? this.options.optimizations.gpu : null;
596597
if (gpu !== false) {
597598
let yPos, xPos;
@@ -611,7 +612,7 @@ class TetherClass extends Evented {
611612
xPos = -_pos.right;
612613
}
613614

614-
if (typeof window.devicePixelRatio === 'number' && devicePixelRatio % 1 === 0) {
615+
if (isNumber(window.devicePixelRatio) && devicePixelRatio % 1 === 0) {
615616
xPos = Math.round(xPos * devicePixelRatio) / devicePixelRatio;
616617
yPos = Math.round(yPos * devicePixelRatio) / devicePixelRatio;
617618
}
@@ -639,7 +640,7 @@ class TetherClass extends Evented {
639640
}
640641
};
641642

642-
const hasOptimizations = typeof this.options.optimizations !== 'undefined';
643+
const hasOptimizations = !isUndefined(this.options.optimizations);
643644
let allowPositionFixed = true;
644645

645646
if (hasOptimizations && this.options.optimizations.allowPositionFixed === false) {
@@ -654,7 +655,7 @@ class TetherClass extends Evented {
654655
} else if (allowPositionFixed && (same.viewport.top || same.viewport.bottom) && (same.viewport.left || same.viewport.right)) {
655656
css.position = 'fixed';
656657
transcribe(same.viewport, pos.viewport);
657-
} else if (typeof same.offset !== 'undefined' && same.offset.top && same.offset.left) {
658+
} else if (!isUndefined(same.offset) && same.offset.top && same.offset.left) {
658659
css.position = 'absolute';
659660
const offsetParent = this.cache('target-offsetparent', () => getOffsetParent(this.target));
660661

@@ -773,8 +774,7 @@ Tether.modules.push({
773774
const offset = offsets[type];
774775
for (let side in offset) {
775776
let val = offset[side];
776-
const notString = typeof val !== 'string';
777-
if (notString ||
777+
if (!isString(val) ||
778778
val.indexOf('%') === -1 &&
779779
val.indexOf('px') === -1) {
780780
val += 'px';

src/js/utils/bounds.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { defer } from './deferred';
22
import { extend, uniqueId } from './general';
3+
import { isUndefined } from './type-check';
34

45
const zeroPosCache = {};
56
let zeroElement = null;
@@ -22,10 +23,10 @@ export function getBounds(el) {
2223
box.top -= origin.top;
2324
box.left -= origin.left;
2425

25-
if (typeof box.width === 'undefined') {
26+
if (isUndefined(box.width)) {
2627
box.width = document.body.scrollWidth - box.left - box.right;
2728
}
28-
if (typeof box.height === 'undefined') {
29+
if (isUndefined(box.height)) {
2930
box.height = document.body.scrollHeight - box.top - box.bottom;
3031
}
3132

@@ -98,7 +99,7 @@ function _getOrigin() {
9899
}
99100

100101
const id = node.getAttribute('data-tether-id');
101-
if (typeof zeroPosCache[id] === 'undefined') {
102+
if (isUndefined(zeroPosCache[id])) {
102103
zeroPosCache[id] = _getActualBoundingClientRect(node);
103104

104105
// Clear the cache when this position call is done

0 commit comments

Comments
 (0)