Vanilla JavaScript: Complete Example
A plain HTML/JS setup with no frameworks. This is the simplest way to integrate the Wedding Band Builder.
With Built-in UI
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Wedding Band Builder</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: system-ui, sans-serif; }
#viewer { width: 100vw; height: 100vh; }
</style>
</head>
<body>
<div id="viewer"></div>
<script src="https://releases.ijewel3d.com/libs/mini-viewer/latest/bundle.iife.js"></script>
<script>
new ijewelViewer.Viewer(document.getElementById('viewer'), {
name: 'Wedding Band Builder',
version: 'v5',
basePath: 'https://your-cdn.com/wbb-assets/',
plugins: {
WeddingBandBuilder: {
manifestUrl: 'wedding-band-project.json',
showUI: true,
},
},
}, {
showCard: false,
showSwitchNode: false,
showUiButtons: true,
showConfigurator: false,
showZoomButtons: true,
enableZoom: true,
});
window.addEventListener('ijewel-viewer-ready', (e) => {
const api = e.detail.viewer.getPluginByType('WeddingBandBuilder').controller;
api.events.on('price:updated', (data) => {
document.title = `Ring - $${data.pricing.totalUsd.toFixed(2)}`;
});
});
</script>
</body>
</html>Headless with Custom Controls
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Custom Wedding Band Configurator</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #fafafa; }
.app { display: flex; flex-direction: column; height: 100vh; }
#viewer { flex: 1; min-height: 300px; }
.controls {
background: #fff;
border-top: 1px solid #e0e0e0;
padding: 16px 24px;
}
.row { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; align-items: center; }
.label { font-size: 12px; font-weight: 600; text-transform: uppercase; color: #888; width: 70px; }
button {
padding: 8px 16px;
border: 1px solid #ddd;
border-radius: 6px;
background: #fff;
cursor: pointer;
font-size: 13px;
}
button:hover { border-color: #999; }
button.active { background: #333; color: #fff; border-color: #333; }
input[type="range"] { width: 180px; }
.price-bar {
padding: 16px 24px;
background: #333;
color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
}
.price { font-size: 24px; font-weight: 600; }
</style>
</head>
<body>
<div class="app">
<div id="viewer"></div>
<div class="controls">
<div class="row">
<span class="label">Profile</span>
<div id="profiles"></div>
</div>
<div class="row">
<span class="label">Metal</span>
<div id="metals"></div>
</div>
<div class="row">
<span class="label">Width</span>
<input id="width" type="range" min="2" max="10" step="0.1" value="4" />
<span id="width-val">4.0 mm</span>
</div>
<div class="row">
<span class="label">Diamonds</span>
<div id="diamonds"></div>
</div>
</div>
<div class="price-bar">
<div>
<button id="btn-her" class="active" onclick="switchBand('her')" style="color:#fff;border-color:rgba(255,255,255,.3);background:rgba(255,255,255,.2)">Her</button>
<button id="btn-his" onclick="switchBand('his')" style="color:#fff;border-color:rgba(255,255,255,.3);background:transparent">His</button>
</div>
<div class="price" id="price">-</div>
</div>
</div>
<script src="https://releases.ijewel3d.com/libs/mini-viewer/latest/bundle.iife.js"></script>
<script>
let api;
new ijewelViewer.Viewer(document.getElementById('viewer'), {
name: 'Wedding Band Builder',
version: 'v5',
basePath: 'https://your-cdn.com/wbb-assets/',
plugins: {
WeddingBandBuilder: {
manifestUrl: 'wedding-band-project.json',
showUI: false,
},
},
}, {
showCard: false, showSwitchNode: false, showUiButtons: false,
showConfigurator: false, showZoomButtons: false, enableZoom: true,
});
window.addEventListener('ijewel-viewer-ready', (e) => {
api = e.detail.viewer.getPluginByType('WeddingBandBuilder').controller;
// Profiles
const profilesEl = document.getElementById('profiles');
api.getAvailableProfiles().forEach((p, i) => {
const btn = document.createElement('button');
btn.textContent = p.name;
if (i === 0) btn.classList.add('active');
btn.onclick = async () => {
await api.setProfile(p.index);
profilesEl.querySelectorAll('button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
};
profilesEl.appendChild(btn);
});
// Metals
const metalsEl = document.getElementById('metals');
api.getAvailableMetals().forEach((m) => {
const btn = document.createElement('button');
btn.textContent = m.name;
btn.onclick = () => api.setMaterial(1, m.id, 'Polished');
metalsEl.appendChild(btn);
});
// Diamonds
const diamondsEl = document.getElementById('diamonds');
const noneBtn = document.createElement('button');
noneBtn.textContent = 'None';
noneBtn.classList.add('active');
noneBtn.onclick = () => {
api.setDiamonds(null);
diamondsEl.querySelectorAll('button').forEach(b => b.classList.remove('active'));
noneBtn.classList.add('active');
};
diamondsEl.appendChild(noneBtn);
api.getAvailableSettingTypes().filter(t => t !== 'none').forEach((t) => {
const btn = document.createElement('button');
btn.textContent = t;
btn.onclick = () => {
api.setDiamonds({ settingType: t });
diamondsEl.querySelectorAll('button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
};
diamondsEl.appendChild(btn);
});
// Width slider
const widthSlider = document.getElementById('width');
const widthVal = document.getElementById('width-val');
const dims = api.getDimensions();
widthSlider.value = dims.widthMm;
widthVal.textContent = dims.widthMm.toFixed(1) + ' mm';
widthSlider.addEventListener('input', (e) => {
const mm = parseFloat(e.target.value);
api.setWidth(mm);
widthVal.textContent = mm.toFixed(1) + ' mm';
});
// Price
api.events.on('price:updated', (data) => {
if (data.pricing) {
document.getElementById('price').textContent = '$' + data.pricing.totalUsd.toFixed(2);
}
});
const price = api.getPrice();
if (price) document.getElementById('price').textContent = '$' + price.totalUsd.toFixed(2);
});
function switchBand(name) {
if (!api) return;
api.switchBand(name);
document.getElementById('btn-her').style.background = name === 'her' ? 'rgba(255,255,255,.2)' : 'transparent';
document.getElementById('btn-his').style.background = name === 'his' ? 'rgba(255,255,255,.2)' : 'transparent';
}
</script>
</body>
</html>