Skip to content

Commit

Permalink
feat: add helpers to detect iOS devices and touch (#3070) (#3074)
Browse files Browse the repository at this point in the history
Co-authored-by: Serhii Kulykov <iamkulykov@gmail.com>
  • Loading branch information
vaadin-bot and web-padawan committed Nov 17, 2021
1 parent fdfbf61 commit db354d9
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 62 deletions.
17 changes: 2 additions & 15 deletions packages/combo-box/src/vaadin-combo-box-dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@ import { IronResizableBehavior } from '@polymer/iron-resizable-behavior/iron-res
import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class.js';
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';

const TOUCH_DEVICE = (() => {
try {
document.createEvent('TouchEvent');
return true;
} catch (e) {
return false;
}
})();

/**
* Element for internal use only.
*
Expand Down Expand Up @@ -47,13 +38,9 @@ export class ComboBoxDropdown extends mixinBehaviors(IronResizableBehavior, Poly
static get properties() {
return {
/**
* True if the device supports touch events.
* True if the combo-box has been activate by the user.
* The actual opened state depends on whether the dropdown has items.
*/
touchDevice: {
type: Boolean,
value: TOUCH_DEVICE
},

opened: Boolean,

/**
Expand Down
5 changes: 3 additions & 2 deletions packages/combo-box/src/vaadin-combo-box-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Copyright (c) 2021 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
import { DisabledMixin } from '@vaadin/component-base/src/disabled-mixin.js';
import { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
import { processTemplates } from '@vaadin/component-base/src/templates.js';
Expand Down Expand Up @@ -360,7 +361,7 @@ export const ComboBoxMixin = (subclass) =>
this._openedWithFocusRing = this.hasAttribute('focus-ring');
// For touch devices, we don't want to popup virtual keyboard
// unless input element is explicitly focused by the user.
if (!this.hasAttribute('focused') && !this.$.dropdown.touchDevice) {
if (!this.hasAttribute('focused') && !isTouch) {
this.focus();
}
} else {
Expand Down Expand Up @@ -609,7 +610,7 @@ export const ComboBoxMixin = (subclass) =>
toggleElement.addEventListener('mousedown', (e) => e.preventDefault());
// Unfocus previously focused element if focus is not inside combo box (on touch devices)
toggleElement.addEventListener('click', () => {
if (this.$.dropdown.touchDevice && !this.hasAttribute('focused')) {
if (isTouch && !this.hasAttribute('focused')) {
document.activeElement.blur();
}
});
Expand Down
32 changes: 25 additions & 7 deletions packages/component-base/src/browser-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,32 @@
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/

export const isAndroid = /android/i.test(navigator.userAgent);
const testUserAgent = (regexp) => regexp.test(navigator.userAgent);

export const isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
const testPlatform = (regexp) => regexp.test(navigator.platform);

export const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
const testVendor = (regexp) => regexp.test(navigator.vendor);

export const isIOS =
(/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
export const isAndroid = testUserAgent(/Android/);

export const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
export const isChrome = testUserAgent(/Chrome/) && testVendor(/Google Inc/);

export const isFirefox = testUserAgent(/Firefox/);

// iPadOS 13 lies and says it's a Mac, but we can distinguish by detecting touch support.
export const isIPad = testPlatform(/^iPad/) || (testPlatform(/^Mac/) && navigator.maxTouchPoints > 1);

export const isIPhone = testPlatform(/^iPhone/);

export const isIOS = isIPhone || isIPad;

export const isSafari = testUserAgent(/^((?!chrome|android).)*safari/i);

export const isTouch = (() => {
try {
document.createEvent('TouchEvent');
return true;
} catch (e) {
return false;
}
})();
12 changes: 2 additions & 10 deletions packages/context-menu/src/vaadin-device-detector.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
import '@polymer/iron-media-query/iron-media-query.js';
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
import { isTouch } from '@vaadin/component-base/src/browser-utils.js';

/**
* Element for internal use only.
Expand Down Expand Up @@ -38,7 +39,7 @@ class DeviceDetector extends PolymerElement {
touch: {
type: Boolean,
notify: true,
value: () => this._touch()
value: isTouch
},

/**
Expand All @@ -51,15 +52,6 @@ class DeviceDetector extends PolymerElement {
};
}

static _touch() {
try {
document.createEvent('TouchEvent');
return true;
} catch (err) {
return false;
}
}

_phone(wide, touch) {
return !wide && touch;
}
Expand Down
17 changes: 7 additions & 10 deletions packages/dialog/src/vaadin-dialog-draggable-mixin.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
/**
* @license
* Copyright (c) 2021 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
import { eventInWindow, getMouseOrFirstTouchEvent } from './vaadin-dialog-utils.js';

const TOUCH_DEVICE = (() => {
try {
document.createEvent('TouchEvent');
return true;
} catch (e) {
return false;
}
})();

/**
* @polymerMixin
*/
Expand Down Expand Up @@ -37,7 +34,7 @@ export const DialogDraggableMixin = (superClass) =>
/** @private */
_touchDevice: {
type: Boolean,
value: TOUCH_DEVICE
value: isTouch
},

/* TODO: Expose as a public property (check naming) */
Expand Down
13 changes: 2 additions & 11 deletions packages/grid/src/vaadin-grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import './vaadin-grid-column.js';
import './vaadin-grid-styles.js';
import { beforeNextRender } from '@polymer/polymer/lib/utils/render-status.js';
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
import { isAndroid, isFirefox, isIOS, isSafari } from '@vaadin/component-base/src/browser-utils.js';
import { isAndroid, isFirefox, isIOS, isSafari, isTouch } from '@vaadin/component-base/src/browser-utils.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { processTemplates } from '@vaadin/component-base/src/templates.js';
import { Virtualizer } from '@vaadin/component-base/src/virtualizer.js';
Expand All @@ -29,15 +29,6 @@ import { SelectionMixin } from './vaadin-grid-selection-mixin.js';
import { SortMixin } from './vaadin-grid-sort-mixin.js';
import { StylingMixin } from './vaadin-grid-styling-mixin.js';

const TOUCH_DEVICE = (() => {
try {
document.createEvent('TouchEvent');
return true;
} catch (e) {
return false;
}
})();

/**
* `<vaadin-grid>` is a free, high quality data grid / data table Web Component. The content of the
* the grid can be populated by using renderer callback function.
Expand Down Expand Up @@ -351,7 +342,7 @@ class Grid extends ElementMixin(
/** @private */
_touchDevice: {
type: Boolean,
value: TOUCH_DEVICE
value: isTouch
},

/**
Expand Down
9 changes: 2 additions & 7 deletions packages/upload/src/vaadin-upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import './vaadin-upload-icons.js';
import './vaadin-upload-file.js';
import { resetMouseCanceller } from '@polymer/polymer/lib/utils/gestures.js';
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';

Expand Down Expand Up @@ -142,13 +143,7 @@ class Upload extends ElementMixin(ThemableMixin(PolymerElement)) {
nodrop: {
type: Boolean,
reflectToAttribute: true,
value: function () {
try {
return !!document.createEvent('TouchEvent');
} catch (e) {
return false;
}
}
value: isTouch
},

/**
Expand Down

0 comments on commit db354d9

Please sign in to comment.