(function () {
'use strict';
if (window.seymourSizePreviews20261016) return;
window.seymourSizePreviews20261016 = true;
if (document.body && document.body.classList.contains('postid-2678')) {
window.location.replace('https://www.seymourjewelers.com/product/lab-diamond-tennis-necklace-in-yellow-gold-5-to-10-ctw/');
return;
}
var products = {
2830: { kind: 'studs', minimum: 0.5, metal: '14K White Gold' },
2841: { kind: 'mixed', minimum: 1 },
2853: { kind: 'necklace', minimum: 5, stock: true },
2946: { kind: 'round', minimum: 1 },
4393: { kind: 'round', minimum: 3, stock: true }
};
var namespace = 'http://www.w3.org/2000/svg';
function svgNode(tag, attributes, parent) {
var node = document.createElementNS(namespace, tag);
Object.keys(attributes || {}).forEach(function (key) { node.setAttribute(key, attributes[key]); });
if (parent) parent.appendChild(node);
return node;
}
function draw(svg, config, weight, metal, length, productId) {
svg.replaceChildren();
var yellow = /Yellow/i.test(metal);
var prefix = 'sj-size-' + productId;
var radius = config.kind === 'studs' ? 11 * Math.cbrt(weight / config.minimum) : 6.5 * Math.sqrt(weight / config.minimum);
if (config.kind === 'necklace' && length) radius *= Math.sqrt(16 / length);
radius = Math.max(5, Math.min(config.kind === 'studs' ? 28 : 22, radius));
svg.dataset.radius = radius.toFixed(3);
svg.dataset.weight = String(weight);
svg.dataset.metal = yellow ? 'yellow' : 'white';
var defs = svgNode('defs', {}, svg);
var diamond = svgNode('radialGradient', { id: prefix + '-diamond', cx: '35%', cy: '25%', r: '80%' }, defs);
[['0%', '#ffffff'], ['48%', '#f5f8fb'], ['100%', '#c9d5df']].forEach(function (s) { svgNode('stop', { offset: s[0], 'stop-color': s[1] }, diamond); });
var gold = svgNode('linearGradient', { id: prefix + '-metal', x1: '0', y1: '0', x2: '1', y2: '1' }, defs);
(yellow ? ['#f2dba4', '#b38738', '#e9cb82'] : ['#edf1f3', '#87949d', '#e0e6eb']).forEach(function (color, i) { svgNode('stop', { offset: (i * 50) + '%', 'stop-color': color }, gold); });
var edge = yellow ? '#b58e46' : '#8b9ba8';
var positions = config.kind === 'studs' ? [145, 255] : [50, 100, 150, 200, 250, 300, 350];
if (config.kind !== 'studs') svgNode('path', { d: 'M26 52 Q200 104 374 52', fill: 'none', stroke: 'url(#' + prefix + '-metal)', 'stroke-width': 3, 'stroke-linecap': 'round' }, svg);
var outlines = [
'M0,-1 C0.58,-0.4 1,0.05 0.72,0.62 C0.4,1.14 -0.4,1.14 -0.72,0.62 C-1,0.05 -0.58,-0.4 0,-1Z',
'M-0.6,-1 H0.6 L0.85,-0.7 V0.7 L0.6,1 H-0.6 L-0.85,0.7 V-0.7Z',
'M0,-1 C1.1,-0.45 1.1,0.45 0,1 C-1.1,0.45 -1.1,-0.45 0,-1Z'
];
positions.forEach(function (x, index) {
var y = config.kind === 'studs' ? 66 : 52 + 26 * (1 - Math.pow((x - 200) / 174, 2));
var group = svgNode('g', { transform: 'translate(' + x + ' ' + y.toFixed(2) + ')' }, svg);
if (config.kind === 'mixed' && index % 4 !== 3) {
var shape = outlines[index % 3];
svgNode('path', { d: shape, transform: 'scale(' + (radius * 1.18).toFixed(3) + ')', fill: 'url(#' + prefix + '-metal)' }, group);
svgNode('path', { d: shape, transform: 'scale(' + radius.toFixed(3) + ')', fill: 'url(#' + prefix + '-diamond)', stroke: '#a6b7c5', 'stroke-width': 0.045 }, group);
svgNode('path', { d: 'M0,-0.68 L0.46,0 L0,0.68 L-0.46,0Z M0,-0.68 V0.68 M-0.46,0 H0.46', transform: 'scale(' + radius.toFixed(3) + ')', fill: 'none', stroke: '#b7c5d1', 'stroke-width': 0.04 }, group);
} else {
svgNode('circle', { r: radius + 2.2, fill: 'url(#' + prefix + '-metal)' }, group);
svgNode('circle', { r: radius, fill: 'url(#' + prefix + '-diamond)', stroke: '#a6b7c5', 'stroke-width': 0.7 }, group);
var points = [];
for (var i = 0; i < 8; i++) {
var angle = (i * Math.PI / 4) + Math.PI / 8;
var outerX = Math.cos(angle) * radius, outerY = Math.sin(angle) * radius;
var innerX = Math.cos(angle) * radius * 0.48, innerY = Math.sin(angle) * radius * 0.48;
points.push(innerX.toFixed(2) + ',' + innerY.toFixed(2));
svgNode('path', { d: 'M' + innerX.toFixed(2) + ',' + innerY.toFixed(2) + 'L' + outerX.toFixed(2) + ',' + outerY.toFixed(2), fill: 'none', stroke: '#b4c4d1', 'stroke-width': 0.7 }, group);
}
svgNode('polygon', { points: points.join(' '), fill: '#ffffff', 'fill-opacity': 0.6, stroke: '#adbfcd', 'stroke-width': 0.65 }, group);
[0, 90, 180, 270].forEach(function (degrees) {
var a = degrees * Math.PI / 180;
svgNode('circle', { cx: Math.cos(a) * (radius + 0.4), cy: Math.sin(a) * (radius + 0.4), r: 1.25, fill: edge }, group);
});
}
});
}
function stockControls($, $form, variations) {
if ($form.data('sj-stock-ready')) return;
var native = $form.find('.variations select').toArray();
var available = variations.filter(function (v) { return v.is_in_stock && v.variation_is_active; });
if (!available.length) return;
var $controls = $('
');
var controls = [];
function current() {
var values = {};
native.forEach(function (select) { values[select.name] = select.value; });
return values;
}
function sync() {
var values = current();
controls.forEach(function (control) {
if (control.select) control.select.val(values[control.key] || '');
if (control.buttons) control.buttons.find('button').each(function () { $(this).attr('aria-pressed', this.dataset.value === values[control.key] ? 'true' : 'false'); });
});
}
function choose(key, value) {
if (!value) return;
var old = current();
var candidates = available.filter(function (v) { return v.attributes[key] === value; });
function score(v) {
return native.reduce(function (total, select) {
var priority = /metal/.test(select.name) ? 16 : (/carat/.test(select.name) ? 8 : 4);
return total + (select.name !== key && old[select.name] && old[select.name] === v.attributes[select.name] ? priority : 0);
}, 0);
}
candidates.sort(function (a, b) { return score(b) - score(a) || a.variation_id - b.variation_id; });
if (!candidates.length) return;
var chosen = candidates[0], changed = [];
native.forEach(function (select) {
var next = chosen.attributes[select.name];
if (select.name !== key && old[select.name] && old[select.name] !== next) changed.push(next);
var option = Array.from(select.options).find(function (o) { return o.value === next; });
if (!option) { option = new Option(next, next); select.add(option); }
option.disabled = false;
select.value = next;
});
$(native[0]).trigger('change');
$form.find('.sj-option-status').text(changed.length ? 'Showing ' + changed.join(' · ') + ' for this option.' : '');
sync();
}
native.forEach(function (select, index) {
var key = select.name;
var label = $(select).closest('tr').find('label').text().trim() || key.replace('attribute_', '').replaceAll('-', ' ');
var values = Array.from(new Set(available.map(function (v) { return v.attributes[key]; }).filter(Boolean)));
values.sort(function (a, b) { return /carat/.test(key) ? parseFloat(a) - parseFloat(b) : a.localeCompare(b); });
var $row = $('
');
if (/carat|length/.test(key)) {
var id = 'sj-stock-' + key.replace('attribute_', '') + '-' + $form.data('product_id') + '-' + index;
$('
').attr('for', id).text(label).appendTo($row);
var $select = $('').attr('id', id).attr('data-attribute', key);
$select.append(new Option(/length/.test(key) ? 'Choose length' : 'Choose carat weight', ''));
values.forEach(function (value) { $select.append(new Option(value, value)); });
$select.on('change', function () { choose(key, this.value); });
$row.append($select); controls.push({ key: key, select: $select });
} else {
$('
').text(label).appendTo($row);
var $buttons = $('
').attr('aria-label', label);
values.forEach(function (value) {
var $button = $('
').attr('data-value', value);
if (/metal/.test(key)) $('
').addClass(/White/.test(value) ? 'sj-white-gold' : 'sj-yellow-gold').appendTo($button);
$('
').text(value).appendTo($button);
$button.on('click', function () { choose(key, value); });
$buttons.append($button);
});
$row.append($buttons); controls.push({ key: key, buttons: $buttons });
}
$controls.append($row);
});
$form.find('.variations').after($controls);
$form.addClass('sj-stock-ready').data('sj-stock-ready', true);
$form.on('found_variation.sjstock reset_data.sjstock woocommerce_variation_has_changed.sjstock', function () { setTimeout(sync, 0); });
sync();
}
function init($, form) {
var $form = $(form), productId = Number($form.data('product_id')), config = products[productId];
if (!config || $form.data('sj-size-ready')) return;
if (config.stock && !$form.hasClass('sj-tennis-options')) return;
var variations = $form.data('product_variations');
if (!Array.isArray(variations)) return;
if (config.stock) stockControls($, $form, variations);
var $card = $('
Relative stone sizeIllustration
');
$card.find('.sj-size-caption').text(config.kind === 'studs' ? 'Approximate illustration, not to scale. CTW is the combined weight of the pair.' : 'Approximate illustration, not to scale. Actual stone count, proportions and settings vary.');
var $anchor = config.stock ? $form.find('.sj-stock-controls') : $form.find('.variations');
$anchor.after($card);
function refresh(variation, reset) {
var values = {};
$form.find('.variations select').each(function () { values[this.name] = this.value; });
if (variation && variation.attributes) Object.assign(values, variation.attributes);
var selected = values['attribute_total-carat-weight'];
var weight = parseFloat(selected), metal = values.attribute_metal || config.metal || '14K White Gold';
if (reset || !weight) {
$card.find('.sj-size-selection').text('Choose a carat weight to preview');
$card.find('svg').attr('hidden', '').empty();
$card.removeAttr('data-weight data-metal');
return;
}
var length = parseFloat(values.attribute_length);
$card.find('.sj-size-selection').text(selected + ' · ' + metal + (length ? ' · ' + values.attribute_length : ''));
$card.attr('data-weight', weight).attr('data-metal', /Yellow/.test(metal) ? 'yellow' : 'white');
var svg = $card.find('svg')[0]; svg.removeAttribute('hidden');
draw(svg, config, weight, metal, length, productId);
}
$form.on('found_variation.sjsize', function (event, variation) { refresh(variation, false); });
$form.on('reset_data.sjsize', function () { refresh(null, true); });
$form.on('woocommerce_variation_has_changed.sjsize', function () { setTimeout(function () { refresh(null, false); }, 0); });
$form.data('sj-size-ready', true);
refresh(null, false);
}
function boot() {
var $ = window.jQuery;
if (!$ || !$.fn.wc_variation_form) return false;
$('form.variations_form').each(function () { init($, this); });
return $('form.variations_form').toArray().every(function (form) { return !products[Number($(form).data('product_id'))] || $(form).data('sj-size-ready'); });
}
var attempts = 0;
function retry() { if (!boot() && attempts++ < 120) setTimeout(retry, 250); }
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', retry, { once: true });
else retry();
})();