@exadel/esl
Version:
Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components
83 lines (82 loc) • 2.9 kB
JavaScript
import { SyntheticEventTarget } from '../../../esl-utils/dom/events';
import { ESLMediaChangeEvent } from './media-query-base';
import { ALL, NOT_ALL } from './media-query-const';
/**
* Abstract multiple media conditions container
* @author Alexey Stsefanovich (ala'n)
*
* Observe all child items. Dispatch changes when the whole condition result is changed
*/
class MediaQueryContainer extends SyntheticEventTarget {
constructor(items = []) {
super();
this.items = items;
this._matches = this.matches;
this._onChange = this._onChange.bind(this);
}
addEventListener(type, callback = type) {
super.addEventListener(type, callback);
if (this.getEventListeners('change').length > 1)
return;
this.items.forEach((item) => item.addEventListener('change', this._onChange));
}
removeEventListener(type, callback = type) {
super.removeEventListener(type, callback);
if (this.hasEventListener())
return;
this.items.forEach((item) => item.removeEventListener('change', this._onChange));
}
optimize() {
return this;
}
get matches() {
return false;
}
/** Handles query change and dispatches it on top level in case result value is changed */
_onChange() {
const { matches } = this;
if (this._matches === matches)
return;
this.dispatchEvent(new ESLMediaChangeEvent(this._matches = matches));
}
}
/** Conjunction (AND) group of media conditions */
export class MediaQueryConjunction extends MediaQueryContainer {
get matches() {
return this.items.every((item) => item.matches);
}
optimize() {
const optimizedItems = this.items.map((item) => item.optimize());
if (optimizedItems.some((item) => NOT_ALL.eq(item)))
return NOT_ALL;
const items = optimizedItems.filter((item) => !ALL.eq(item));
if (items.length === 0)
return ALL;
if (items.length === 1)
return items[0];
return new MediaQueryConjunction(items);
}
toString() {
return this.items.join(' and ');
}
}
/** Disjunction (OR) group of media conditions */
export class MediaQueryDisjunction extends MediaQueryContainer {
get matches() {
return this.items.some((item) => item.matches);
}
optimize() {
const optimizedItems = this.items.map((item) => item.optimize());
if (optimizedItems.some((item) => ALL.eq(item)))
return ALL;
const items = optimizedItems.filter((item) => !NOT_ALL.eq(item));
if (items.length === 0)
return NOT_ALL;
if (items.length === 1)
return items[0];
return new MediaQueryDisjunction(items);
}
toString(pretty = false) {
return this.items.join(pretty ? ' or ' : ', ');
}
}