Автокраны XCMG в Москве — официальный дилер ТИГР

Продолжая использовать данный сайт, Вы даете согласие об использовании файлов cookie, пользовательских данных,
в том числе с использованием Яндекс.Метрика в целях сбора статистики посещения сайта.
Если вы не хотите, чтобы ваши данные обрабатывались, сделайте соответствующую настройку браузера или покиньте данный сайт.
Мы используем cookie и Яндекс.Метрику. Подробнее

Даю согласие
logo logo
Продажа дорожно-строительной, карьерной техники XCMG
Сургут

+7 (3462) 64-43-14

Telegram MAX — техника MAX — сервис и запчасти MAX

Поставка от 3х дней

info-xcmg@tigr86.ru

Заказать звонок
Главная » Автокраны в Москве

Автокраны XCMG в Москве — официальный дилер ТИГР

ТИГР продаёт крановую технику XCMG через головной офис в д. Пуршево (г. о. Балашиха, Московская область): шоссейные автокраны и автокраны-вездеходы (полноприводные), гусеничные, короткобазные и башенные краны. Подобрать модель и оформить покупку можно в офисе или по телефону. Технику поставляем со складов в России или под заказ с завода. Есть ли нужная модель в наличии, подтверждаем по заявке. Разделы каталога:

Запчасти: запчасти для автокранов и запчасти XCMG в Москве. Сервис: сервис XCMG в Москве. Лизинг: условия лизинга.

Головной офис: Московская область, д. Пуршево, ул. Новослободская, д. 66, 8 800 101 88 98. Подробности и карта — на странице филиала в Москве.

Москва — головной офис

Адрес: Московская область, д. Пуршево, ул. Новослободская, д. 66

Тел: 8 800 101 88 98 (бесплатно по России)

Email: info-xcmg@tigr86.ru

Время работы: Пн–Пт 9:00–18:00

WATGMAXтехникаMAXсервисзапчастиMAX
: null; } function isTeleCrawlerCraneList() { return /^\/catalogue\/krany\/gusenichnye-krany-s-teleskopicheskoj-streloj\/?$/.test(pagePath()); } function isCrawlerExcavatorList() { return /^\/catalogue\/ekskavatory\/gusenichnye-ekskavatory\/?$/.test(pagePath()); } function isMiniExcavatorList() { return /^\/catalogue\/ekskavatory\/mini-ekskavatory\/?$/.test(pagePath()); } function isFrontLoaderList() { return /^\/catalogue\/pogruzchiki\/frontalnye-pogruzchiki\/?$/.test(pagePath()); } function isQuickButtonList() { return isCrawlerExcavatorList() || isMiniExcavatorList() || isFrontLoaderList(); } function wheeledPower(value, label) { var n = num(value); if (/квт|kw/i.test(label)) { var hp = String(value).match(/\(\s*([0-9]+(?:[.,][0-9]+)?)\s*(?:л\.?\s*с\.?)?\s*\)/i); if (hp) return num(hp[1]); return Math.round(n * 1.35962 * 100) / 100; } return n; } /* Canonical spec keys: label regexp -> key, unit, converter */ var SPEC_KEYS = [ {k: 'weight', label: 'Масса, т', re: /(эксплуатац|операцион|рабоч|полн|снаряж)?.*(масса|вес)(?!.*(груз|ковш))/i, conv: function (v, l) { return /кг|kg/i.test(l) ? v / 1000 : v; }}, {k: 'power', label: 'Мощность, л.с.', re: /мощн/i, conv: function (v, l) { return /квт|kw/i.test(l) ? Math.round(v * 1.36) : v; }}, {k: 'bucket', label: 'Ковш, м³', re: /(объ[её]м|обьем|вместимост|[её]мкост).{0,40}ковш|ковш.{0,40}(объ[её]м|обьем|вместимост|[её]мкост)|ковш\s*[,:(]?\s*м\s*[³3]|^\s*ковш\s*$/i, conv: function (v) { return v; }, skip: /усили|пальц|диаметр|ширин|длин|высот|ковшев|тип\s*ковш/i}, {k: 'lift', label: 'Грузоподъёмность, т', re: /грузоподъ[её]мн/i, conv: function (v, l) { return /кг|kg/i.test(l) ? v / 1000 : v; }}, {k: 'height', label: 'Высота подъёма, м', re: /высот.*подъ/i, conv: function (v) { return v; }}, {k: 'depth', label: 'Глубина копания, м', re: /глубин.*(копан|бурен)/i, conv: function (v, l) { return /мм|mm/i.test(l) ? v / 1000 : v; }} ]; function specKey(label) { for (var i = 0; i < SPEC_KEYS.length; i++) { var d = SPEC_KEYS[i]; if (d.re.test(label) && !(d.skip && d.skip.test(label))) return d; } return null; } /* ---------- models.json (lazy, shared) ---------- */ var modelsP = null; function loadModels() { if (modelsP) return modelsP; if (window.XM_MODELS) { modelsP = Promise.resolve(window.XM_MODELS.items || window.XM_MODELS); return modelsP; } modelsP = fetch(MODELS_URL, {credentials: 'omit'}).then(function (r) { return r.ok ? r.json() : {items: []}; }) .then(function (j) { return j.items || []; }).catch(function () { return []; }); return modelsP; } /* ===================================================================== * 1+2+4. CATEGORY PAGES: subcategory tiles, grid, filter bar, «Показать все» * ===================================================================== */ function initCategory() { var right = $('.catalogue-products-list-rightside'); if (!right || $('.catalogue-proudctpage-block')) return; // not a listing, or a product page var items = $$('.catalogue-products-list-item', right); if (!items.length) return; var list = right.closest('.catalogue-products-list'); var h1 = $('.workarea-block h1'); // Split into subcategory items (link ends with "/") and product items. var subs = [], prods = []; items.forEach(function (it) { var a = $('.catalogue-products-list-item-name', it); if (!a) return; (/\/$/.test(a.getAttribute('href') || '') ? subs : prods).push(it); }); // --- 1. Subcategory tiles (category page with children) --- if (subs.length && !$('.xm-subtiles')) { var wrap = el('div', 'xm-subtiles'); subs.forEach(function (it) { var a = $('.catalogue-products-list-item-name', it), img = $('.catalogue-products-list-item-photo img', it); var t = el('a', 'xm-subtile'); t.href = a.getAttribute('href'); if (img) t.style.backgroundImage = "url('" + img.getAttribute('src') + "')"; t.innerHTML = '' + esc(txt(a)) + ''; wrap.appendChild(t); it.classList.add('xm-hidden'); }); insertAfterIntro(wrap); document.body.classList.add('xm-has-subtiles'); } // --- 1b. Leaf category: sibling subcategories as chips (from the header mega-menu) --- if (!subs.length && prods.length && !$('.xm-subtiles')) { var here = path(pagePath()), parent = here.replace(/[^\/]+\/$/, ''); var top = $$('#catalog_tec li.li_sec_catalog > a').filter(function (a) { return path(a.getAttribute('href')) === parent; })[0]; var sibs = top ? $$('.catalog_subtec a', top.parentNode) : []; if (sibs.length > 1) { var chips = el('div', 'xm-subtiles xm-subtiles--chips'); sibs.forEach(function (a) { var c = el('a', 'xm-chip' + (path(a.getAttribute('href')) === here ? ' is-active' : ''), esc(txt(a))); c.href = a.getAttribute('href'); chips.appendChild(c); }); insertAfterIntro(chips); } } if (!prods.length) return; // --- 2. Grid of cards --- list.classList.add('xm-listing'); right.classList.add('xm-grid'); var cards = prods.map(function (it) { return enhanceCard(it); }); // Left column contains only the (often empty) filter on leaf pages -> collapse it, filter goes on top. var left = $('.catalogue-products-list-leftside', list); if (left && !$('.catalogue-products-scroll', left)) left.classList.add('xm-left-collapsed'); // --- 4. Visible filter bar --- buildFilterBar(cards, right, left); } function insertAfterIntro(node) { var intro = $('.workarea-block .introtext') || $('.workarea-block h1'); if (intro) intro.parentNode.insertBefore(node, intro.nextSibling); } // Parse "Label: value
" lines; tag card with data-xm-* numbers; keep max 4 specs. function enhanceCard(it) { it.classList.add('xm-card'); var attrs = $('.catalogue-products-list-item-attributes', it), specs = [], data = {}; if (attrs) { attrs.innerHTML.split(//i).forEach(function (line) { var tmp = el('div', null, line), v = $('span', tmp), label, value; if (v) { value = txt(v); v.remove(); label = txt(tmp).replace(/:\s*$/, ''); } else { var p = txt(tmp).split(':'); if (p.length < 2) return; label = p.shift(); value = p.join(':').trim(); } if (!label || !value) return; specs.push({label: label, value: value}); var d = specKey(label), n = num(value); if (d && !isNaN(n) && data[d.k] == null) { data[d.k] = isWheeledExcavatorList() && d.k === 'power' ? wheeledPower(value, label) : d.conv(n, label); } }); var ul = el('ul', 'xm-specs'); specs.slice(0, 4).forEach(function (s) { ul.appendChild(el('li', null, '' + esc(s.label) + '' + esc(s.value) + '')); }); attrs.classList.add('xm-hidden'); attrs.parentNode.insertBefore(ul, attrs); } SPEC_KEYS.forEach(function (d) { // server-rendered data-xm-* (from TVs) wins over parsed text var a = it.getAttribute('data-xm-' + d.k), n = a ? num(a) : NaN; if (!isNaN(n)) data[d.k] = n; }); Object.keys(data).forEach(function (k) { it.setAttribute('data-xm-' + k, data[k]); }); var name = $('.catalogue-products-list-item-name', it); it.setAttribute('data-xm-name', norm(txt(name))); // photo first, compact CTA row var photo = $('.catalogue-products-list-item-photo', it); if (photo) it.insertBefore(photo, it.firstChild); var btns = $$('.catalogue-products-list-item-info > .catalogue-product-list-item-properties', it).pop(); if (btns) btns.classList.add('xm-ctas'); $$('.catalogue-products-list-item-info > br', it).forEach(function (b) { b.remove(); }); return {node: it, data: data, name: it.getAttribute('data-xm-name'), title: txt(name)}; } function buildFilterBar(cards, right, left) { var serverFilters = $$('.filter_cont'); var bar = el('div', 'xm-filterbar'); if (isWheeledExcavatorList()) bar.classList.add('xm-wheel-filter-mobile-safe'); if (isCrawlerCraneList() || isTeleCrawlerCraneList() || craneLiftBtns()) bar.classList.add('xm-crane-tonnage'); if (isQuickButtonList()) bar.classList.add('xm-quick-btns'); var fields = []; // a) server filter (custom snippet, GET ?{tv}_min/_max) exists -> keep it, just show it expanded on top if (serverFilters.length && left) { var fd = $('.filter_div', left), fn = $('.filter_name_cont', left); if (fd) { fd.classList.add('act', 'xm-serverfilter'); if (fn) fn.classList.add('act'); bar.appendChild(fd); } } else if (isCrawlerCraneList()) { // Section 17: four tonnage buttons instead of moment/hp/kW sliders. Counts follow published cards in the DOM. var tons = el('div', 'xm-f xm-f--tons'); tons.innerHTML = '
' + '' + '' + '' + '' + '
'; bar.appendChild(tons); } else if (isTeleCrawlerCraneList()) { // Section 1501: three tonnage buttons. Future XGTC160 (160 t) fits in «свыше 80 т». var tons = el('div', 'xm-f xm-f--tons'); tons.innerHTML = '
' + '' + '' + '' + '
'; bar.appendChild(tons); } else if (craneLiftBtns()) { var tons = el('div', 'xm-f xm-f--tons'); tons.innerHTML = '
' + '' + craneLiftBtns() + '
'; bar.appendChild(tons); } else if (isCrawlerExcavatorList()) { var tons = el('div', 'xm-f xm-f--tons'); tons.innerHTML = '
' + '' + '' + '' + '' + '
'; bar.appendChild(tons); } else if (isMiniExcavatorList()) { var tons = el('div', 'xm-f xm-f--tons'); tons.innerHTML = '
' + '' + '' + '' + '
'; bar.appendChild(tons); } else if (isFrontLoaderList()) { var buckets = el('div', 'xm-f xm-f--tons'); buckets.innerHTML = '
' + '' + '' + '' + '
'; bar.appendChild(buckets); var lifts = el('div', 'xm-f xm-f--tons'); lifts.innerHTML = '
' + '' + '' + '' + '
'; bar.appendChild(lifts); } else { // b) client-side numeric filters for keys present on >= 50% of cards with real spread SPEC_KEYS.forEach(function (d) { var vals = cards.map(function (c) { return c.data[d.k]; }).filter(function (v) { return v != null && !isNaN(v); }); if (vals.length < Math.max(2, cards.length * 0.5)) return; var mn = Math.min.apply(null, vals), mx = Math.max.apply(null, vals); if (mn === mx || fields.length >= 3) return; var f = el('div', 'xm-f'); f.innerHTML = '
' + '' + '–
'; bar.appendChild(f); fields.push(d.k); }); } // model text filter + sort + counter (always) var q = el('div', 'xm-f xm-f--q', ''); bar.appendChild(q); var sortOpts = ''; // size order: model number decides inside one series (XE60 < XE215 < XE690, QY25 < QY160); // series are placed against each other by a spec score (average percentile of weight/power/lift/bucket) var SZ = ['weight', 'power', 'lift', 'bucket']; function clean(k, v) { if (v == null || isNaN(v)) return null; if ((k === 'weight' || k === 'lift') && v >= 1000) v = v / 1000; // kg typed into a "т" field if (k === 'bucket' && v > 50) return null; if (k === 'power' && v < 20) return null; return v; } function modelInfo(c) { var t = (c.title || '').replace(/XCMG/ig, ' '), m = t.match(/([A-ZА-Я]{1,4})[\s_-]?(\d+(?:[.,]\d+)?)/i); return m ? {p: m[1].toUpperCase(), n: parseFloat(m[2].replace(',', '.'))} : {p: '', n: null}; } var pct = {}; SZ.forEach(function (k) { var vals = cards.map(function (c) { return clean(k, c.data[k]); }).filter(function (v) { return v != null; }).sort(function (a, b) { return a - b; }); if (vals.length < 2) return; pct[k] = function (v) { var lo = 0, hi = 0; vals.forEach(function (x) { if (x < v) lo++; if (x <= v) hi++; }); return ((lo + hi - 1) / 2) / (vals.length - 1); }; }); cards.forEach(function (c) { c.mi = modelInfo(c); var sum = 0, n = 0; SZ.forEach(function (k) { var v = clean(k, c.data[k]); if (pct[k] && v != null) { sum += pct[k](v); n++; } }); c.sz = n ? sum / n : null; }); var series = {}; cards.forEach(function (c) { if (c.mi.n != null) (series[c.mi.p] = series[c.mi.p] || []).push(c); }); Object.keys(series).forEach(function (p) { var list = series[p].sort(function (a, b) { return a.mi.n - b.mi.n; }); var known = list.filter(function (c) { return c.sz != null; }); if (!known.length) { list.forEach(function (c, i) { c.sz = null; }); return; } // fill gaps from the nearest known neighbours in model-number order list.forEach(function (c, i) { if (c.sz != null) return; var l = null, r = null, j; for (j = i - 1; j >= 0; j--) if (list[j].sz != null) { l = list[j].sz; break; } for (j = i + 1; j < list.length; j++) if (list[j].sz != null) { r = list[j].sz; break; } c.szTmp = l != null && r != null ? (l + r) / 2 : (l != null ? l : r); }); list.forEach(function (c) { if (c.szTmp != null) { c.sz = c.szTmp; delete c.szTmp; } }); // same scores, handed out in model-number order (equal numbers keep a shared slot) var scores = list.map(function (c) { return c.sz; }).sort(function (a, b) { return a - b; }); var i = 0; while (i < list.length) { var j = i; while (j + 1 < list.length && list[j + 1].mi.n === list[i].mi.n) j++; var avg = 0; for (var t = i; t <= j; t++) avg += scores[t]; avg /= (j - i + 1); for (t = i; t <= j; t++) list[t].sz = avg; i = j + 1; } }); var noKey = cards.every(function (c) { return c.sz == null; }); function sizeCmp(a, b) { var x = noKey ? a.mi.n : a.sz, y = noKey ? b.mi.n : b.sz; if (x == null && y != null) return 1; if (y == null && x != null) return -1; if (x != null && y != null && x !== y) return x - y; if (a.mi.n != null && b.mi.n != null && a.mi.n !== b.mi.n) return a.mi.n - b.mi.n; return a.title.localeCompare(b.title, 'ru', {numeric: true}); } bar.appendChild(el('div', 'xm-f xm-f--sort', '')); var foot = el('div', 'xm-f xm-f--foot', ''); bar.appendChild(foot); right.parentNode.insertBefore(bar, right); if (left && left.classList.contains('xm-left-collapsed') && !$('.filter_cont', bar)) left.classList.add('xm-hidden'); var original = cards.slice(); var more = el('button', 'xm-more'); more.type = 'button'; right.parentNode.insertBefore(more, right.nextSibling); var expanded = false; more.addEventListener('click', function () { expanded = true; apply(); }); function apply() { var qv = norm($('[data-b="q"]', bar).value), rng = {}; $$('input[data-k]', bar).forEach(function (i) { var v = num(i.value); if (!isNaN(v)) (rng[i.dataset.k] = rng[i.dataset.k] || {})[i.dataset.b] = v; }); var btnGroups = $$('.xm-ton-btns', bar).map(function (wrap) { var btn = $('.xm-ton-btn.is-active', wrap); var key = (wrap.getAttribute('data-filter-key') || 'lift'); var spec = {key: key, active: !!(btn && btn.getAttribute('data-ton') !== 'all'), min: NaN, max: NaN, gt: NaN, lt: NaN}; if (btn) { if (btn.hasAttribute('data-ton-min')) spec.min = num(btn.getAttribute('data-ton-min')); if (btn.hasAttribute('data-ton-max')) spec.max = num(btn.getAttribute('data-ton-max')); if (btn.hasAttribute('data-ton-gt')) spec.gt = num(btn.getAttribute('data-ton-gt')); if (btn.hasAttribute('data-ton-lt')) spec.lt = num(btn.getAttribute('data-ton-lt')); } return spec; }); var hasTon = btnGroups.some(function (g) { return g.active; }); var sv = $('[data-b="sort"]', bar).value, list = original.slice(); if (sv === 'size') list.sort(sizeCmp); else if (sv === 'size-desc') list.sort(function (a, b) { return sizeCmp(b, a); }); else if (sv === 'name') list.sort(function (a, b) { return a.title.localeCompare(b.title, 'ru', {numeric: true}); }); else if (sv) { var p = sv.split(':'), k = p[0], dir = +p[1]; list.sort(function (a, b) { var x = a.data[k], y = b.data[k]; if (x == null) return 1; if (y == null) return -1; return (x - y) * dir; }); } var shown = 0, matched = 0, filtering = !!qv || Object.keys(rng).length > 0 || hasTon; list.forEach(function (c) { var ok = !qv || c.name.indexOf(qv) > -1; Object.keys(rng).forEach(function (k) { var v = c.data[k]; if (v == null) { ok = false; return; } if (rng[k].min != null && v < rng[k].min) ok = false; if (rng[k].max != null && v > rng[k].max) ok = false; }); btnGroups.forEach(function (g) { if (!g.active) return; var v = c.data[g.key]; if (v == null || isNaN(v)) { ok = false; return; } if (!isNaN(g.min) && v < g.min) ok = false; if (!isNaN(g.max) && v > g.max) ok = false; if (!isNaN(g.gt) && v <= g.gt) ok = false; if (!isNaN(g.lt) && v >= g.lt) ok = false; }); right.appendChild(c.node); // re-order if (ok) matched++; var vis = ok && (expanded || filtering || matched <= PAGE_SIZE); c.node.classList.toggle('xm-hidden', !vis); if (vis) shown++; }); $('.xm-count', bar).textContent = 'Найдено: ' + matched + ' из ' + original.length; more.textContent = 'Показать все (' + matched + ')'; more.style.display = shown < matched ? '' : 'none'; var empty = $('.xm-empty', right); if (!matched && !empty) right.appendChild(el('div', 'xm-empty', 'Ничего не нашлось. Сбросьте фильтр или позвоните: 8-800-101-88-98')); if (matched && empty) empty.remove(); } bar.addEventListener('input', debounce(apply, 150)); bar.addEventListener('change', apply); $$('.xm-ton-btns', bar).forEach(function (tonWrap) { tonWrap.addEventListener('click', function (e) { var b = e.target.closest ? e.target.closest('.xm-ton-btn') : null; if (!b || !tonWrap.contains(b)) return; $$('.xm-ton-btn', tonWrap).forEach(function (x) { x.classList.toggle('is-active', x === b); }); apply(); }); }); $('.xm-reset', bar).addEventListener('click', function () { $$('input', bar).forEach(function (i) { if (!i.closest('.xm-serverfilter')) i.value = ''; }); $$('.xm-ton-btn', bar).forEach(function (b) { b.classList.toggle('is-active', b.getAttribute('data-ton') === 'all'); }); $('[data-b="sort"]', bar).value = 'size'; apply(); if ($('.xm-serverfilter', bar) && location.search) location.href = location.pathname; }); $$('.xm-ton-btns', bar).forEach(function (wrap) { var key = wrap.getAttribute('data-filter-key') || 'lift'; $$('.xm-ton-btn', wrap).forEach(function (b) { if (b.getAttribute('data-ton') === 'all') return; var minV = b.hasAttribute('data-ton-min') ? num(b.getAttribute('data-ton-min')) : NaN; var maxV = b.hasAttribute('data-ton-max') ? num(b.getAttribute('data-ton-max')) : NaN; var gtV = b.hasAttribute('data-ton-gt') ? num(b.getAttribute('data-ton-gt')) : NaN; var ltV = b.hasAttribute('data-ton-lt') ? num(b.getAttribute('data-ton-lt')) : NaN; var n = cards.filter(function (c) { var v = c.data[key]; if (v == null || isNaN(v)) return false; if (!isNaN(minV) && v < minV) return false; if (!isNaN(maxV) && v > maxV) return false; if (!isNaN(gtV) && v <= gtV) return false; if (!isNaN(ltV) && v >= ltV) return false; return true; }).length; if (!n) b.style.display = 'none'; }); }); apply(); } function debounce(fn, ms) { var t; return function () { clearTimeout(t); t = setTimeout(fn, ms); }; } /* ===================================================================== * 3. HEADER SEARCH with autocomplete over models.json * ===================================================================== */ function initSearch() { if ($('.xm-search')) return; var host = $('[data-xm-search]') || // optional placeholder from the header chunk $('header .header__container .cont .cont_1'); if (!host) return; var box = el('form', 'xm-search'); box.setAttribute('role', 'search'); box.action = window.XM_SEARCH_URL || '/catalogue/'; box.method = 'get'; box.innerHTML = '' + '' + ''; if (host.hasAttribute && host.hasAttribute('data-xm-search')) host.appendChild(box); else host.parentNode.insertBefore(box, host.nextSibling); var input = $('input', box), res = $('.xm-search-res', box), idx = -1, cur = []; function render(list, q) { cur = list; idx = -1; if (!q) { res.hidden = true; return; } res.innerHTML = list.length ? list.map(function (m, i) { return '
  • ' + (m.i ? '' : '') + '' + esc(m.t) + '' + esc(m.sc || m.c || '') + '
  • '; }).join('') : '
  • Не нашли «' + esc(q) + '». Позвоните: 8-800-101-88-98
  • '; res.hidden = false; } function search(q) { var nq = norm(q); if (nq.length < 2) { render([], ''); return; } loadModels().then(function (items) { var words = q.toLowerCase().split(/\s+/).filter(Boolean).map(norm); var scored = []; items.forEach(function (m) { var nt = m._n || (m._n = norm(m.t + ' ' + (m.sc || '') + ' ' + (m.c || ''))); var model = m._m || (m._m = norm((m.t.match(/XCMG\s+(.+)$/i) || [, m.t])[1])); var s = 0; if (model.indexOf(nq) === 0) s = 100 - model.length; else if (model.indexOf(nq) > -1) s = 60; else if (words.every(function (w) { return nt.indexOf(w) > -1; })) s = 30; if (s) scored.push({m: m, s: s}); }); scored.sort(function (a, b) { return b.s - a.s || a.m.t.localeCompare(b.m.t, 'ru', {numeric: true}); }); render(scored.slice(0, 8).map(function (x) { return x.m; }), q); }); } input.addEventListener('focus', function () { loadModels(); if (input.value) search(input.value); }); input.addEventListener('input', debounce(function () { search(input.value); }, 120)); input.addEventListener('keydown', function (e) { var links = $$('a', res); if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { e.preventDefault(); if (!links.length) return; idx = (idx + (e.key === 'ArrowDown' ? 1 : -1) + links.length) % links.length; links.forEach(function (a, i) { a.classList.toggle('is-active', i === idx); }); } else if (e.key === 'Escape') { res.hidden = true; } }); box.addEventListener('submit', function (e) { e.preventDefault(); var pick = cur[idx > -1 ? idx : 0]; if (pick) location.href = pick.u; else if (window.XM_SEARCH_URL && input.value.trim()) location.href = window.XM_SEARCH_URL + '?q=' + encodeURIComponent(input.value.trim()); else search(input.value); }); document.addEventListener('click', function (e) { if (!box.contains(e.target)) res.hidden = true; }); } /* ===================================================================== * 5. PRODUCT PAGE: gallery, key figures + CTA, collapsible specs, PDF, similar models * ===================================================================== */ function initProduct() { var block = $('.catalogue-proudctpage-block'); // (sic) class name in live template if (!block) return; document.body.classList.add('xm-product'); var info = $('.catalogue-productpage-infoblock', block), imgBox = $('.catalogue-productpage-image', block); var h1 = $('h1', info), title = txt(h1); block.classList.add('xm-pp'); if (imgBox) block.insertBefore(imgBox, block.firstChild); // photo left, info right // --- gallery --- var main = imgBox && $('.catalogue-productpage-detailpictureitem img', imgBox); var items = []; // {f: full-size url, t: thumbnail url} var orig = function (u) { return (u || '').replace(/\/resize_cache(\/iblock\/[^\/]+)\/\d+_\d+_\d+\//, '/iblock$1/'); }; // Bitrix thumb -> original var fname = function (u) { return (u || '').split('/').pop(); }; if (main) items.push({f: main.getAttribute('src'), t: main.getAttribute('src')}); var extra = $('[data-xm-images]'); // optional:
    from a TV if (extra) extra.getAttribute('data-xm-images').split(/\|\||,|\n/).forEach(function (s) { s = s.trim(); if (s) items.push({f: s, t: s}); }); $$('.catalogue-productpage-thumbnailitem').forEach // NB: thumbs block sits OUTSIDE .catalogue-productpage-image (unbalanced divs in template) (function (t) { var src = t.getAttribute('src'); if (src) items.push({f: t.getAttribute('data-full') || orig(src), t: src}); }); var names = items.map(function (o) { return fname(o.f); }); items = items.filter(function (o, i) { return o.f && names.indexOf(fname(o.f)) === i; }); var srcs = items.map(function (o) { return o.f; }); if (main) { var g = el('div', 'xm-gallery'); var stage = el('a', 'xm-gallery-main'); stage.href = srcs[0]; stage.setAttribute('data-fancybox', 'xm-gallery'); stage.setAttribute('data-caption', title); stage.appendChild(main.cloneNode(true)); $('img', stage).alt = title; g.appendChild(stage); if (srcs.length > 1) { var th = el('div', 'xm-gallery-thumbs'); srcs.forEach(function (s, i) { var b = el('button', i ? '' : 'is-active'); b.type = 'button'; b.innerHTML = '' + esc(title) + ' фото ' + (i + 1) + ''; b.addEventListener('click', function () { $('img', stage).src = s; stage.href = s; $$('button', th).forEach(function (x) { x.classList.toggle('is-active', x === b); }); }); th.appendChild(b); if (i) { var hid = el('a', 'xm-hidden'); hid.href = s; hid.setAttribute('data-fancybox', 'xm-gallery'); g.appendChild(hid); } }); g.appendChild(th); } imgBox.innerHTML = ''; imgBox.appendChild(g); $$('.catalogue-productpage-images, .catalogue-productpage-thumbs').forEach(function (x) { x.classList.add('xm-hidden'); }); // old strips (one sits loose after the image box) } // --- specs table: key figures + collapse --- var body = $('.catalogue-productpage-properties-body'); var rows = body ? $$('.catalogue-productpage-properties-row', body) : []; var facts = [], seen = {}; rows.forEach(function (r) { var l = txt($('.catalogue-productpage-properties-value1', r)), v = txt($('.catalogue-productpage-properties-value2', r)); var d = specKey(l), n = num(v); if (d && !seen[d.k] && !isNaN(n) && facts.length < 4) { seen[d.k] = 1; facts.push({l: d.label.split(',')[0], v: fmt(d.conv(n, l)), u: (d.label.split(', ')[1] || '')}); } if (/двигатель.*модел|модель двигател/i.test(l) && !seen.engine && facts.length < 4) { seen.engine = 1; facts.push({l: 'Двигатель', v: v.replace(/^engine\s+/i, ''), u: ''}); } }); if (facts.length) { var kf = el('ul', 'xm-keyfacts'); facts.forEach(function (f) { kf.appendChild(el('li', null, '' + esc(f.v) + (f.u ? ' ' + esc(f.u) + '' : '') + '' + esc(f.l) + '')); }); var after = $('.catalogue-productpage-pricevalue', info) || h1; after.parentNode.insertBefore(kf, after.nextSibling); } // CTA: keep «Узнать цену», add «Заказать технику» (same popup, same data-product -> same form handler) var cta = $('.catalogue-products-list-item-price', info); if (cta && !$('.popup-price', cta)) { cta.classList.add('xm-pp-ctas'); var order = el('a', 'popup-price xm-btn-outline', /^\/catalogue\/navesnoe-oborudovanie(?:\/|$)/.test(location.pathname) ? 'Быстрый заказ' : 'Заказать технику'); order.setAttribute('data-product', title); order.setAttribute('data-fancybox', ''); order.setAttribute('data-type', 'ajax'); order.setAttribute('data-touch', 'false'); order.setAttribute('href', ''); order.setAttribute('data-url', 'popup-price'); cta.appendChild(order); } // PDF brochure: explicit [data-xm-brochure] (from a TV) or any .pdf link in the description var pdf = $('[data-xm-brochure]'), pdfHref = pdf ? pdf.getAttribute('data-xm-brochure') : null; if (!pdfHref) { var a = $$('.catalogue-productpage-descriptionblock a[href$=".pdf"], .catalogue-productpage-descriptionblock a[href*=".pdf?"]')[0]; if (a) pdfHref = a.getAttribute('href'); } if (pdfHref && cta) { var pl = el('a', 'xm-pdf', 'Скачать брошюру (PDF)'); pl.href = pdfHref; pl.target = '_blank'; pl.rel = 'noopener'; cta.parentNode.insertBefore(pl, cta.nextSibling); } if (body && rows.length > SPECS_VISIBLE) { body.classList.add('xm-specs-collapsed'); rows.forEach(function (r, i) { if (i >= SPECS_VISIBLE) r.classList.add('xm-spec-extra'); }); var t = el('button', 'xm-specs-toggle'); t.type = 'button'; var lbl = function () { t.textContent = body.classList.contains('xm-specs-collapsed') ? 'Показать все характеристики (' + rows.length + ')' : 'Свернуть характеристики'; }; t.addEventListener('click', function () { body.classList.toggle('xm-specs-collapsed'); lbl(); }); lbl(); body.parentNode.appendChild(t); } // --- similar models (server block wins if the template already renders .xm-similar) --- if (!$('.xm-similar')) { var here = pagePath().replace(/\/$/, ''); loadModels().then(function (items) { var me = items.filter(function (m) { return m.u.replace(/\/$/, '') === here; })[0]; var dir = here.replace(/\/[^\/]+$/, '/'); var pool = items.filter(function (m) { return m.u !== (me && me.u) && m.u.replace(/\/$/, '') !== here && m.u.indexOf(dir) === 0; }); if (pool.length < 4 && me) pool = pool.concat(items.filter(function (m) { return m.c === me.c && m.u.indexOf(dir) !== 0; })); if (!pool.length) return; // nearest by position in the sorted list (≈ similar size), then fill var pos = me ? items.indexOf(me) : 0; pool.sort(function (a, b) { return Math.abs(items.indexOf(a) - pos) - Math.abs(items.indexOf(b) - pos); }); var sec = el('section', 'xm-similar', '

    Похожие модели

    '); pool.slice(0, 4).forEach(function (m) { $('.xm-similar-grid', sec).appendChild(el('a', 'xm-sim', '' + esc(m.t) + '' + esc(m.t) + '' + (m.s ? '' + esc(m.s.split('; ').slice(0, 2).join(' · ')) + '' : ''))); $('.xm-similar-grid', sec).lastChild.href = m.u; }); var anchor = $('.catalogue-productpage-descriptionblock') || block; anchor.parentNode.insertBefore(sec, anchor.nextSibling); }); } } function boot() { try { initSearch(); } catch (e) { window.console && console.warn('xm search', e); } try { initCategory(); } catch (e) { window.console && console.warn('xm category', e); } try { initProduct(); } catch (e) { window.console && console.warn('xm product', e); } document.documentElement.classList.add('xm-ready'); } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot); else boot(); })(); `]]