Skip to content

Commit

Permalink
#921@trivial: Continues on implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
capricorn86 committed May 15, 2023
1 parent 2e4f047 commit 38b68d5
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 304 deletions.
10 changes: 10 additions & 0 deletions packages/happy-dom/src/match-media/IMediaQueryItem.ts
@@ -0,0 +1,10 @@
import MediaQueryDeviceEnum from './MediaQueryDeviceEnum';

/**
* Media query item.
*/
export default interface IMediaQueryItem {
device: MediaQueryDeviceEnum;
not: boolean;
rule: { key: string; value: string | null };
}
10 changes: 5 additions & 5 deletions packages/happy-dom/src/match-media/MediaQueryDeviceEnum.ts
@@ -1,7 +1,7 @@
enum SelectorCombinatorEnum {
descendant = 'descendant',
child = 'child',
adjacentSibling = 'adjacentSibling'
enum MediaQueryDeviceEnum {
all = 'all',
print = 'print',
screen = 'screen'
}

export default SelectorCombinatorEnum;
export default MediaQueryDeviceEnum;
21 changes: 0 additions & 21 deletions packages/happy-dom/src/match-media/MediaQueryItem.ts

This file was deleted.

97 changes: 82 additions & 15 deletions packages/happy-dom/src/match-media/MediaQueryList.ts
Expand Up @@ -3,9 +3,9 @@ import Event from '../event/Event';
import IWindow from '../window/IWindow';
import IEventListener from '../event/IEventListener';
import MediaQueryListEvent from '../event/events/MediaQueryListEvent';

const MEDIA_REGEXP =
/min-width: *([0-9]+) *px|max-width: *([0-9]+) *px|min-height: *([0-9]+) *px|max-height: *([0-9]+) *px/;
import IMediaQueryItem from './IMediaQueryItem';
import MediaQueryParser from './MediaQueryParser';
import MediaQueryDeviceEnum from './MediaQueryDeviceEnum';

/**
* Media Query List.
Expand All @@ -17,6 +17,7 @@ export default class MediaQueryList extends EventTarget {
public readonly media: string = '';
public onchange: (event: Event) => void = null;
private _ownerWindow: IWindow;
private _items: IMediaQueryItem[] = [];

/**
* Constructor.
Expand All @@ -27,7 +28,8 @@ export default class MediaQueryList extends EventTarget {
constructor(ownerWindow: IWindow, media: string) {
super();
this._ownerWindow = ownerWindow;
this.media = media;
this._items = MediaQueryParser.getMediaQueryItems(media);
this.media = this._items.length > 0 ? media : 'not all';
}

/**
Expand All @@ -36,19 +38,17 @@ export default class MediaQueryList extends EventTarget {
* @returns Matches.
*/
public get matches(): boolean {
const match = this.media.match(MEDIA_REGEXP);
if (match) {
if (match[1]) {
return this._ownerWindow.innerWidth >= parseInt(match[1]);
} else if (match[2]) {
return this._ownerWindow.innerWidth <= parseInt(match[2]);
} else if (match[3]) {
return this._ownerWindow.innerHeight >= parseInt(match[3]);
} else if (match[4]) {
return this._ownerWindow.innerHeight <= parseInt(match[4]);
if (!this._items.length || this.media === 'not all') {
return false;
}

for (const item of this._items) {
if (!this._matchesItem(item)) {
return false;
}
}
return false;

return true;
}

/**
Expand Down Expand Up @@ -102,4 +102,71 @@ export default class MediaQueryList extends EventTarget {
this._ownerWindow.removeEventListener('resize', listener['_windowResizeListener']);
}
}

/**
*
* @param item
*/
private _matchesItem(item: IMediaQueryItem): boolean {
if (
item.device === MediaQueryDeviceEnum.print ||
(item.not &&
(item.device === MediaQueryDeviceEnum.screen || item.device === MediaQueryDeviceEnum.all))
) {
return false;
}

switch (item.rule.key) {
case 'min-width':
const minWidth = parseInt(item.rule.value, 10);
return !isNaN(minWidth) && this._ownerWindow.innerWidth >= minWidth;
case 'max-width':
const maxWidth = parseInt(item.rule.value, 10);
return !isNaN(maxWidth) && this._ownerWindow.innerWidth <= maxWidth;
case 'min-height':
const minHeight = parseInt(item.rule.value, 10);
return !isNaN(minHeight) && this._ownerWindow.innerHeight >= minHeight;
case 'max-height':
const maxHeight = parseInt(item.rule.value, 10);
return !isNaN(maxHeight) && this._ownerWindow.innerHeight <= maxHeight;
case 'orientation':
return item.rule.value === 'landscape'
? this._ownerWindow.innerWidth > this._ownerWindow.innerHeight
: this._ownerWindow.innerWidth < this._ownerWindow.innerHeight;
case 'prefers-color-scheme':
return item.rule.value === this._ownerWindow.happyDOM.settings.colorScheme;
case 'hover':
return item.rule.value === 'none'
? this._ownerWindow.navigator.maxTouchPoints === 0
: this._ownerWindow.navigator.maxTouchPoints > 0;
case 'any-pointer':
case 'pointer':
return item.rule.value === 'none' || item.rule.value === 'fine'
? this._ownerWindow.navigator.maxTouchPoints === 0
: this._ownerWindow.navigator.maxTouchPoints > 0;
case 'display-mode':
return item.rule.value === 'browser';
case 'min-aspect-ratio':
case 'max-aspect-ratio':
case 'aspect-ratio':
const aspectRatio = item.rule.value.split('/');
const width = parseInt(aspectRatio[0], 10);
const height = parseInt(aspectRatio[1], 10);

if (isNaN(width) || isNaN(height)) {
return false;
}

switch (item.rule.key) {
case 'min-aspect-ratio':
return width / height <= this._ownerWindow.innerWidth / this._ownerWindow.innerHeight;
case 'max-aspect-ratio':
return width / height >= this._ownerWindow.innerWidth / this._ownerWindow.innerHeight;
case 'aspect-ratio':
return width / height === this._ownerWindow.innerWidth / this._ownerWindow.innerHeight;
}
}

return false;
}
}

0 comments on commit 38b68d5

Please sign in to comment.