MOOER
About
MOODER
Cargando familias de productos…
Compare (0/5)
152 products
Filter
/* microFusa: direct children from Father collection. No writes or tokens. */
(() => {
if (customElements.get('mf-lg-father-loader')) return;
class MfLgFatherLoader extends HTMLElement {
connectedCallback() {
if (this.life) return;
this.life = new AbortController();
this.status = this.querySelector('[data-mf-status]');
this.retry = this.querySelector('[data-mf-retry]');
this.results = this.querySelector('[data-mf-results]');
this.grid = this.querySelector('.collection-grid');
this.seed = this.querySelector('template[data-mf-page]');
this.retry.addEventListener('click', () => this.load(), {signal: this.life.signal});
this.grid.addEventListener('scroll', () => this.updateArrows(), {signal: this.life.signal});
this.addEventListener('click', event => {
const button = event.target.closest('.flickity-nav');
if (!button || !this.contains(button)) return;
const cards = this.grid.children;
const step = cards.length > 1 ? cards[1].offsetLeft - cards[0].offsetLeft : this.grid.clientWidth;
this.grid.scrollBy({left: button.name === 'prev' ? -step : step,
behavior: matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth'});
}, {signal: this.life.signal});
this.observer = new ResizeObserver(() => this.updateArrows());
this.observer.observe(this.grid);
this.load();
}
disconnectedCallback() {
this.life?.abort();
this.request?.abort();
this.observer?.disconnect();
cancelAnimationFrame(this.frame);
this.life = null;
}
announce(text) {
cancelAnimationFrame(this.frame);
this.status.textContent = '';
this.frame = requestAnimationFrame(() => { this.status.textContent = text; });
}
updateArrows() {
const previous = this.querySelector('.flickity-prev');
const next = this.querySelector('.flickity-next');
const maximum = this.grid.scrollWidth - this.grid.clientWidth;
if (previous) previous.disabled = this.grid.scrollLeft <= 1;
if (next) next.disabled = maximum <= 1 || this.grid.scrollLeft >= maximum - 1;
}
async load() {
this.request?.abort();
const controller = new AbortController();
this.request = controller;
const fromRetry = document.activeElement === this.retry;
this.setAttribute('aria-busy', 'true');
this.retry.disabled = true;
this.results.hidden = true;
this.status.classList.remove('mf-lg-status-done');
this.announce(this.dataset.loading);
const cards = new Map();
try {
if (!this.seed) throw new Error('Missing pagination metadata');
const total = Number(this.seed.dataset.total);
const pages = Math.max(1, Number(this.seed.dataset.pages));
const initialPage = Number(this.seed.dataset.page);
const parent = this.seed.dataset.parent;
if (!Number.isInteger(total) || total < 0 || total > 25000 ||
!Number.isInteger(pages) || pages > 100 || initialPage < 1 || initialPage > pages) {
throw new Error('Unsupported pagination range');
}
let scanned = 0;
for (let page = 1; page <= pages; page += 1) {
if (controller.signal.aborted) return;
let template = this.seed;
if (page !== initialPage) {
const url = new URL(window.location.href);
url.searchParams.delete('sections');
url.searchParams.delete('section_id');
url.searchParams.set('section_id', this.dataset.section);
url.searchParams.set(this.seed.dataset.param || 'page', String(page));
const timer = setTimeout(() => controller.abort(), 20000);
let response;
let html;
try {
response = await fetch(url, {signal: controller.signal, credentials: 'same-origin'});
if (!response.ok) throw new Error(`Section HTTP ${response.status}`);
html = await response.text();
} finally { clearTimeout(timer); }
const documentPage = new DOMParser().parseFromString(html, 'text/html');
const loader = documentPage.querySelector('mf-lg-father-loader');
if (!loader || loader.dataset.section !== this.dataset.section) throw new Error('Wrong section');
template = loader.querySelector('template[data-mf-page]');
}
if (!template || Number(template.dataset.page) !== page ||
Number(template.dataset.total) !== total ||
Math.max(1, Number(template.dataset.pages)) !== pages || template.dataset.parent !== parent) {
throw new Error('Pagination context changed or incomplete');
}
const pageScanned = Number(template.dataset.scanned);
const expected = Math.min(250, Math.max(0, total - (page - 1) * 250));
if (pageScanned !== expected) throw new Error('Truncated collection page');
scanned += pageScanned;
for (const child of template.content.querySelectorAll('template[data-mf-child]')) {
const card = child.content.firstElementChild;
if (!card) throw new Error('Missing child card');
cards.set(child.dataset.mfChild, {id: child.dataset.mfChild, title: child.dataset.title, card});
}
this.announce(`${this.dataset.loading} (${scanned}/${total})`);
}
if (!this.isConnected || this.request !== controller || controller.signal.aborted) return;
if (scanned !== total) throw new Error('Incomplete collection coverage');
const ordered = [...cards.values()].sort((a, b) =>
a.title.localeCompare(b.title, document.documentElement.lang || undefined, {sensitivity: 'base'}) || a.id.localeCompare(b.id));
const fragment = document.createDocumentFragment();
for (const item of ordered) fragment.appendChild(item.card.cloneNode(true));
this.grid.replaceChildren(fragment);
this.dataset.scanned = String(scanned);
this.dataset.total = String(total);
this.dataset.children = String(ordered.length);
this.dataset.state = 'complete';
this.results.hidden = ordered.length === 0;
this.retry.hidden = true;
this.status.classList.add('mf-lg-status-done');
this.removeAttribute('aria-busy');
this.announce(this.dataset.done);
this.updateArrows();
if (fromRetry) this.grid.querySelector('a')?.focus();
} catch (error) {
if (!this.isConnected || this.request !== controller) return;
this.dataset.state = 'error';
this.results.hidden = true;
this.retry.hidden = false;
this.retry.disabled = false;
this.removeAttribute('aria-busy');
this.announce(this.dataset.error);
console.warn('[microFusa LG father lookup]', error);
}
}
}
customElements.define('mf-lg-father-loader', MfLgFatherLoader);
})();
Mooer GS 1000 Li
Regular price
451,00 €
Sale price
451,00 €
Regular price
455,00 €
Unit price
/per
○
Delivery in 1-2 days
Mooer GS 1000
Regular price
385,00 €
Sale price
385,00 €
Regular price
399,00 €
Unit price
/per
○
Delivery in 1-2 days
MOOER PDC5S MULTI DC STRAIGHT CABLE
Regular price
4,00 €
Sale price
4,00 €
Regular price
Unit price
/per
○
Delivery in 2-4 days
MOOER MOOER SKYVERB DIGITAL REVERB
Regular price
64,00 €
Sale price
64,00 €
Regular price
Unit price
/per
○
Delivery in 1-2 days
MOOER SD50A ACOUSTIC AMPLIFIER
Regular price
344,00 €
Sale price
344,00 €
Regular price
Unit price
/per
○
Check availability
Mooer Mod Factory
Regular price
85,00 €
Sale price
85,00 €
Regular price
Unit price
/per
○
Check availability
Mooer GE 300 Lite
Regular price
455,00 €
Sale price
455,00 €
Regular price
Unit price
/per
○
Check availability
Mooer GE 300
Regular price
526,00 €
Sale price
526,00 €
Regular price
Unit price
/per
○
Delivery in 2-4 days
Mooer Micro DI Cabinet
Regular price
60,00 €
Sale price
60,00 €
Regular price
Unit price
/per
○
Check availability
Mooer Reverie Reverb
Regular price
124,00 €
Sale price
124,00 €
Regular price
Unit price
/per
○
Check availability
Mooer Lofi Machine Effects Pedal
Regular price
67,00 €
Sale price
67,00 €
Regular price
Unit price
/per
○
Check availability
Mooer Repeater
Regular price
64,00 €
Sale price
64,00 €
Regular price
Unit price
/per
○
Check availability