formstone
Version:
Library of modular front end components.
119 lines (93 loc) • 2.6 kB
JavaScript
import {
iterate,
//
on,
} from './utils.js';
// Class
class MediaQuery {
static #_bindings = {};
static bind(key, media, data) {
key = this.#createKey(key);
let mq = window.matchMedia(media);
let mqKey = this.#createKey(mq.media);
if (!this.#_bindings[mqKey]) {
this.#_bindings[mqKey] = {
mq: mq,
active: true,
enter: {},
leave: {}
};
on(mq, 'change', (e) => {
this.#onBindingChange(e);
});
}
iterate(Object.entries(data), (entry) => {
let action = entry[0];
let cb = entry[1];
if (this.#_bindings[mqKey][action]) {
if (this.#_bindings[mqKey][action][key]) {
console.warn(`MediaQuery: '${key}' ${media} already exists and can not be bound`);
// TODO short circuit here?
} else {
this.#_bindings[mqKey][action][key] = cb;
}
}
});
// Check Match
let binding = this.#_bindings[mqKey];
if (mq.matches && binding.enter[key]) {
binding.enter[key].apply(mq);
binding.active = true;
} else if (!mq.matches && binding.leave[key]) {
binding.leave[key].apply(mq);
binding.active = false;
}
}
static unbind(key, media) {
if (!key) {
return;
}
if (media) {
// Unbind specific MQ
var mqKey = this.#createKey(media);
if (this.#_bindings[mqKey]) {
if (this.#_bindings[mqKey].enter[key]) {
delete this.#_bindings[mqKey].enter[key];
}
if (this.#_bindings[mqKey].leave[key]) {
delete this.#_bindings[mqKey].leave[key];
}
}
} else {
// Unbind all
iterate(Object.entries(this.#_bindings), (entry) => {
// let mqKey = entry[0];
let binding = entry[1];
if (binding.enter[key]) {
delete binding.enter[key];
}
if (binding.leave[key]) {
delete binding.leave[key];
}
});
}
}
static #onBindingChange(e) {
let mqkey = MediaQuery.#createKey(e.media);
let binding = this.#_bindings[mqkey];
let action = e.matches ? 'enter' : 'leave';
if (binding && (binding.active || (!binding.active && e.matches))) {
iterate(Object.entries(binding[action]), (entry) => {
// let key = entry[0];
let cb = entry[1];
cb.apply(binding.mq);
});
binding.active = true;
}
}
static #createKey(text) {
return text.replace(/[^a-z0-9\s]/gi, '').replace(/[_\s]/g, '').replace(/^\s+|\s+$/g, '');
}
};
// Export
export default MediaQuery;