• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SAP / ui5-webcomponents-react / 13679209638

05 Mar 2025 03:14PM CUT coverage: 87.434%. First build
13679209638

Pull #7036

github

web-flow
Merge 7a8055b75 into e6246058b
Pull Request #7036: chore(deps): update ui5 web components react (examples & templates) to v2.7.4 (patch)

2926 of 3883 branches covered (75.35%)

5114 of 5849 relevant lines covered (87.43%)

47649.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.57
/packages/base/src/Device/index.ts
1
import { supportsTouch } from '@ui5/webcomponents-base/dist/Device.js';
2
import type { IOrientation, IWindowSize } from './EventProvider.js';
3
import { OrientationEventProvider, ResizeEventProvider } from './EventProvider.js';
4

5
const isSSR = () => typeof window === 'undefined';
444✔
6

7
const getActualWindowSize = (): [width: number, height: number] => {
426✔
8
  if (isSSR()) {
444!
9
    return [0, 0];
×
10
  }
11
  return [window.innerWidth, window.innerHeight];
444✔
12
};
13

14
let iResizeTimeout;
15
let bOrientationChange = false;
426✔
16
let bResize = false;
426✔
17
let iOrientationTimeout;
18
let iClearFlagTimeout;
19
let [iWindowWidthOld, iWindowHeightOld] = getActualWindowSize();
426✔
20
const rInputTagRegex = /INPUT|TEXTAREA|SELECT/;
426✔
21

22
const internalWindowSize: IWindowSize = {
426✔
23
  height: 0,
24
  width: 0
25
};
26

27
const internalOrientation: IOrientation = {
426✔
28
  landscape: false,
29
  portrait: false
30
};
31

32
// PRIVATE API
33

34
const isLandscape = () => {
426✔
35
  return !!window.matchMedia('(orientation: landscape)').matches;
25✔
36
};
37

38
const setResizeInfo = () => {
426✔
39
  internalWindowSize.width = getActualWindowSize()[0];
9✔
40
  internalWindowSize.height = getActualWindowSize()[1];
9✔
41
};
42

43
const setOrientationInfo = () => {
426✔
44
  internalOrientation.landscape = isLandscape();
11✔
45
  internalOrientation.portrait = !internalOrientation.landscape;
11✔
46
};
47

48
const clearFlags = () => {
426✔
49
  bOrientationChange = false;
×
50
  bResize = false;
×
51
  iClearFlagTimeout = null;
×
52
};
53

54
let eventListenersInitialized = false;
426✔
55
const initEventListeners = () => {
426✔
56
  // Add handler for orientationchange and resize after initialization of Device API
57
  if (supportsTouch()) {
3!
58
    // logic for mobile devices which support orientationchange (like ios, android)
59
    window.addEventListener('resize', handleMobileOrientationResizeChange, false);
×
60
    window.addEventListener('orientationchange', handleMobileOrientationResizeChange, false);
×
61
  } else {
62
    // desktop browsers and windows phone/tablet which not support orientationchange
63
    window.addEventListener('resize', handleResizeEvent, false);
3✔
64
  }
65
  setResizeInfo();
3✔
66
  setOrientationInfo();
3✔
67
  eventListenersInitialized = true;
3✔
68
};
69

70
// orientation change
71
const handleOrientationChange = () => {
426✔
72
  setOrientationInfo();
8✔
73
  OrientationEventProvider.fireEvent('orientation', {
8✔
74
    landscape: internalOrientation.landscape,
75
    portrait: internalOrientation.portrait
76
  });
77
};
78

79
const handleMobileTimeout = () => {
426✔
80
  // with ios split view, the browser fires only resize event and no orientationchange
81
  // when changing the size of a split view
82
  // therefore the following if needs to be adapted with additional check of iPad with version greater or equal 9
83
  // (splitview was introduced with iOS 9)
84
  if (bResize && bOrientationChange) {
×
85
    handleOrientationChange();
×
86
    handleResizeChange();
×
87
    bOrientationChange = false;
×
88
    bResize = false;
×
89
    if (iClearFlagTimeout) {
×
90
      window.clearTimeout(iClearFlagTimeout);
×
91
      iClearFlagTimeout = null;
×
92
    }
93
  }
94
  iOrientationTimeout = null;
×
95
};
96

97
const handleMobileOrientationResizeChange = (evt) => {
426✔
98
  if (evt.type === 'resize') {
×
99
    if (rInputTagRegex.test(document.activeElement?.tagName) && !bOrientationChange) {
×
100
      return;
×
101
    }
102

103
    const [iWindowWidthNew, iWindowHeightNew] = getActualWindowSize();
×
104
    // skip multiple resize events by only one orientationchange
105
    if (iWindowHeightNew === iWindowHeightOld && iWindowWidthNew === iWindowWidthOld) {
×
106
      return;
×
107
    }
108
    bResize = true;
×
109
    // on mobile devices opening the keyboard on some devices leads to a resize event
110
    // in this case only the height changes, not the width
111
    if (iWindowHeightOld !== iWindowHeightNew && iWindowWidthOld === iWindowWidthNew) {
×
112
      handleResizeChange();
×
113
    } else {
114
      iWindowWidthOld = iWindowWidthNew;
×
115
    }
116
    iWindowHeightOld = iWindowHeightNew;
×
117

118
    if (iClearFlagTimeout) {
×
119
      window.clearTimeout(iClearFlagTimeout);
×
120
      iClearFlagTimeout = null;
×
121
    }
122
    // Some Android build-in browser fires a resize event after the viewport is applied.
123
    // This resize event has to be dismissed otherwise when the next orientationchange event happens,
124
    // a UI5 resize event will be fired with the wrong window size.
125
    iClearFlagTimeout = window.setTimeout(clearFlags, 1200);
×
126
  } else if (evt.type === 'orientationchange') {
×
127
    bOrientationChange = true;
×
128
  }
129

130
  if (iOrientationTimeout) {
×
131
    clearTimeout(iOrientationTimeout);
×
132
    iOrientationTimeout = null;
×
133
  }
134
  iOrientationTimeout = window.setTimeout(handleMobileTimeout, 50);
×
135
};
136

137
// RESIZE ONLY WITHOUT ORIENTATION CHANGE
138
const handleResizeChange = () => {
426✔
139
  setResizeInfo();
6✔
140
  ResizeEventProvider.fireEvent('resize', {
6✔
141
    height: internalWindowSize.height,
142
    width: internalWindowSize.width
143
  });
144
};
145

146
const handleResizeTimeout = () => {
426✔
147
  handleResizeChange();
6✔
148
  iResizeTimeout = null;
6✔
149
};
150

151
const handleResizeEvent = () => {
426✔
152
  const wasL = internalOrientation.landscape;
14✔
153
  const isL = isLandscape();
14✔
154
  if (wasL !== isL) {
14✔
155
    handleOrientationChange();
8✔
156
  }
157
  // throttle resize events because most browsers throw one or more resize events per pixel
158
  // for every resize event inside the period from 150ms (starting from the first resize event),
159
  // we only fire one resize event after this period
160
  if (!iResizeTimeout) {
14✔
161
    iResizeTimeout = window.setTimeout(handleResizeTimeout, 150);
8✔
162
  }
163
};
164

165
// re-export everything from the web components device
166
export * from '@ui5/webcomponents-base/dist/Device.js';
167
// export all media methods
168
export { attachMediaHandler, detachMediaHandler, getCurrentRange } from './Media.js';
169

170
// resize events
171
export const attachResizeHandler = (fnFunction: (windowSize: IWindowSize) => void): void => {
426✔
172
  if (!eventListenersInitialized) {
3✔
173
    initEventListeners();
3✔
174
  }
175
  ResizeEventProvider.attachEvent('resize', fnFunction);
3✔
176
};
177

178
export const detachResizeHandler = (fnFunction: (windowSize: IWindowSize) => void) => {
426✔
179
  ResizeEventProvider.detachEvent('resize', fnFunction);
3✔
180
};
181

182
// orientation change events
183
export const getOrientation = (): IOrientation => {
426✔
184
  return internalOrientation;
×
185
};
186

187
export const attachOrientationChangeHandler = (fnFunction: (orientation: IOrientation) => void): void => {
426✔
188
  if (!eventListenersInitialized) {
2!
189
    initEventListeners();
×
190
  }
191
  OrientationEventProvider.attachEvent('orientation', fnFunction);
2✔
192
};
193

194
export const detachOrientationChangeHandler = (fnFunction: (orientation: IOrientation) => void) => {
426✔
195
  OrientationEventProvider.detachEvent('orientation', fnFunction);
2✔
196
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc