As described in our Privacy Policy, we collect personal information from your interactions with us and our website, including through cookies and similar technologies. We may also share this personal information with third parties, including advertising partners. We do this in order to show you ads on other websites that are more relevant to your interests and for other reasons outlined in our privacy policy.
Sharing of personal information for targeted advertising based on your interaction on different websites may be considered "sales", "sharing", or "targeted advertising" under certain U.S. state privacy laws. Depending on where you live, you may have the right to opt out of these activities. If you would like to exercise this opt-out right, please follow the instructions below.
If you visit our website with the Global Privacy Control opt-out preference signal enabled, depending on where you are, we will treat this as a request to opt-out of activity that may be considered a “sale” or “sharing” of personal information or other uses that may be considered targeted advertising for the device and browser you used to visit our website.
Find Your Part By Brand and Model OR OEM Part Number
Loading...
Loading products...
(function() {
var STOREFRONT_TOKEN = '023adb4fad851d8f82aa1eefdb4ed95c';
var SHOP_DOMAIN = 'meckorn.com';
var API_URL = 'https://' + SHOP_DOMAIN + '/api/2025-01/graphql.json';
var PER_PAGE = 24;
var allProducts = [];
var selections = { brand: '', model: '', barLength: '', pitch: '', gauge: '', dl: '' };
var currentPage = 1;
var QUERY = 'query GetChainProducts($cursor: String) {'
+ ' products(first: 50, after: $cursor, query: "product_type:*Chainsaw Chain*") {'
+ ' pageInfo { hasNextPage endCursor }'
+ ' edges { node {'
+ ' id title handle'
+ ' featuredImage { url altText }'
+ ' priceRange { minVariantPrice { amount currencyCode } }'
+ ' barLength: metafield(namespace: "custom", key: "bar_length") { value }'
+ ' pitch: metafield(namespace: "custom", key: "pitch") { value }'
+ ' gauge: metafield(namespace: "custom", key: "gauge") { value }'
+ ' driveLinks: metafield(namespace: "custom", key: "drive_links") { value }'
+ ' modelRef: metafield(namespace: "custom", key: "model") {'
+ ' references(first: 25) { nodes { ... on Metaobject {'
+ ' modelField: field(key: "model") { value }'
+ ' brandRef: field(key: "numbers") { reference { ... on Metaobject { displayName: field(key: "name") { value } } } }'
+ ' } } }'
+ ' }'
+ ' } } }'
+ '}';
function gql(query, variables) {
return fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': STOREFRONT_TOKEN
},
body: JSON.stringify({ query: query, variables: variables || {} })
}).then(function(res) { return res.json(); });
}
function fetchAllProducts() {
var products = [];
var cursor = null;
var hasMore = true;
function next() {
if (!hasMore) return Promise.resolve(products);
return gql(QUERY, { cursor: cursor }).then(function(data) {
var conn = data && data.data && data.data.products;
if (!conn) return products;
conn.edges.forEach(function(edge) {
var node = edge.node;
var brands = [], models = [];
var nodes = (node.modelRef && node.modelRef.references && node.modelRef.references.nodes) || [];
nodes.forEach(function(mo) {
var modelVal = mo.modelField && mo.modelField.value;
if (modelVal) {
modelVal.split(/[,\uff0c]/).forEach(function(s) {
var t = s.trim();
if (t) models.push(t);
});
}
var brandName = mo.brandRef && mo.brandRef.reference && mo.brandRef.reference.displayName && mo.brandRef.reference.displayName.value;
if (brandName && brands.indexOf(brandName) === -1) brands.push(brandName);
});
products.push({
id: node.id,
title: node.title,
handle: node.handle,
imageUrl: node.featuredImage ? node.featuredImage.url : null,
imageAlt: node.featuredImage ? node.featuredImage.altText : node.title,
price: node.priceRange && node.priceRange.minVariantPrice ? node.priceRange.minVariantPrice.amount : null,
currency: node.priceRange && node.priceRange.minVariantPrice ? node.priceRange.minVariantPrice.currencyCode : null,
_dims: {
brand: brands,
model: models,
barLength: node.barLength && node.barLength.value ? [node.barLength.value] : [],
pitch: node.pitch && node.pitch.value ? [node.pitch.value] : [],
gauge: node.gauge && node.gauge.value ? [node.gauge.value] : [],
dl: node.driveLinks && node.driveLinks.value ? [node.driveLinks.value] : []
}
});
});
hasMore = conn.pageInfo.hasNextPage;
cursor = conn.pageInfo.endCursor;
return next();
});
}
return next();
}
function getOptions(dim) {
var others = Object.keys(selections).filter(function(d) { return d !== dim; });
var compatible = allProducts.filter(function(p) {
return others.every(function(d) {
if (!selections[d]) return true;
var vals = p._dims[d];
return !vals || vals.length === 0 || vals.indexOf(selections[d]) !== -1;
});
});
var set = {};
compatible.forEach(function(p) {
(p._dims[dim] || []).forEach(function(v) { if (v) set[v] = true; });
});
return Object.keys(set).sort(function(a, b) {
return a.localeCompare(b, undefined, { numeric: true });
});
}
function getMatched() {
return allProducts.filter(function(p) {
return Object.keys(selections).every(function(d) {
if (!selections[d]) return true;
var vals = p._dims[d];
return !vals || vals.length === 0 || vals.indexOf(selections[d]) !== -1;
});
});
}
function formatPrice(amount, currency) {
if (!amount) return '';
try {
return new Intl.NumberFormat(undefined, { style: 'currency', currency: currency || 'USD' }).format(amount);
} catch(e) {
return '$' + parseFloat(amount).toFixed(2);
}
}
function renderDropdown(dim) {
var input = document.querySelector('input[data-dim="' + dim + '"]');
var ul = document.querySelector('.cf-dropdown[data-dim="' + dim + '"]');
if (!input || !ul) return;
var opts = getOptions(dim);
var query = input.value.trim().toLowerCase();
var effectiveQuery = (query && query !== (selections[dim] || '').toLowerCase()) ? query : '';
var filtered = effectiveQuery ? opts.filter(function(o) { return o.toLowerCase().indexOf(effectiveQuery) !== -1; }) : opts;
ul.innerHTML = '';
if (selections[dim]) {
var li = document.createElement('li');
li.className = 'clear-item';
li.textContent = '— Clear selection —';
li.addEventListener('mousedown', function(e) {
e.preventDefault();
selections[dim] = '';
input.value = '';
input.classList.remove('has-value');
updateAll();
});
ul.appendChild(li);
}
if (filtered.length === 0) {
var li2 = document.createElement('li');
li2.className = 'no-match';
li2.textContent = effectiveQuery ? 'No matches' : 'No options available';
ul.appendChild(li2);
} else {
filtered.forEach(function(opt) {
var li3 = document.createElement('li');
li3.textContent = opt;
if (opt === selections[dim]) li3.classList.add('selected');
li3.addEventListener('mousedown', function(e) {
e.preventDefault();
selections[dim] = opt;
input.value = opt;
input.classList.add('has-value');
ul.classList.remove('open');
updateAll();
});
ul.appendChild(li3);
});
}
}
function renderResults() {
var matched = getMatched();
var total = matched.length;
var totalPages = Math.max(1, Math.ceil(total / PER_PAGE));
if (currentPage > totalPages) currentPage = 1;
var paged = matched.slice((currentPage - 1) * PER_PAGE, currentPage * PER_PAGE);
document.getElementById('cf-count').textContent = total + ' product' + (total !== 1 ? 's' : '') + ' matched';
var grid = document.getElementById('cf-grid');
if (paged.length === 0) {
grid.innerHTML = '
No products match your selection. Try adjusting your filters.
';
} else {
var html = '';
paged.forEach(function(p) {
var imgHtml = p.imageUrl
? ''
: '