User:Monster Domosed/common.js: Difference between revisionsGive feedback
No edit summary |
load on demand |
||
| Line 5: | Line 5: | ||
const HQ_ICON = '/images/1/10/HQ_icon.png'; | const HQ_ICON = '/images/1/10/HQ_icon.png'; | ||
function | function getSize(wrapper) { | ||
const match = wrapper.className.match(/model_size_(\d+)/); | const match = wrapper.className.match(/model_size_(\d+)/); | ||
return match ? parseInt(match[1], 10) : 500; | |||
} | |||
function updateViewerSize(viewer, wrapper) { | |||
const size = getSize(wrapper); | |||
const size = | |||
viewer.style.width = size + 'px'; | viewer.style.width = size + 'px'; | ||
| Line 18: | Line 17: | ||
} | } | ||
function | function updateQualityButtonSize(button, wrapper) { | ||
const size = getSize(wrapper); | |||
const size = | |||
const buttonSize = Math.max(28, Math.min(56, Math.round(size * 0.14))); | const buttonSize = Math.max(28, Math.min(56, Math.round(size * 0.14))); | ||
| Line 34: | Line 26: | ||
} | } | ||
function | function getFileUrl(fileName) { | ||
const apiUrl = | const apiUrl = | ||
mw.config.get('wgScriptPath') + | mw.config.get('wgScriptPath') + | ||
'/api.php?action=query' + | '/api.php?action=query' + | ||
'&titles=File:' + encodeURIComponent(fileName) + | '&titles=File:' + encodeURIComponent(fileName) + | ||
'&prop=imageinfo' + | '&prop=imageinfo' + | ||
'&iiprop=url' + | '&iiprop=url' + | ||
| Line 49: | Line 40: | ||
}) | }) | ||
.then(function (data) { | .then(function (data) { | ||
const page = Object.values(data.query.pages)[0]; | |||
const page = Object.values(pages)[0]; | |||
if (!page.imageinfo) { | if (!page.imageinfo) { | ||
| Line 60: | Line 50: | ||
} | } | ||
function | function addQualityButton(wrapper, viewer, lqUrl, hqUrl) { | ||
if (!hqUrl || lqUrl === hqUrl) { | |||
return; | return; | ||
} | } | ||
const | const button = document.createElement('button'); | ||
button.className = 'mv-quality-toggle'; | |||
button.type = 'button'; | |||
updateQualityButtonSize(button, wrapper); | |||
const | const icon = document.createElement('img'); | ||
icon.src = LQ_ICON; | |||
icon.alt = ''; | |||
button.appendChild(icon); | |||
viewer. | button.addEventListener('click', function () { | ||
const isLQ = viewer.src === lqUrl; | |||
viewer.src = isLQ ? hqUrl : lqUrl; | |||
icon.src = isLQ ? HQ_ICON : LQ_ICON; | |||
}); | |||
wrapper.appendChild(button); | |||
} | |||
if ( | function loadModel(wrapper) { | ||
if (wrapper.dataset.loaded) { | |||
return; | return; | ||
} | } | ||
wrapper.dataset.loaded = '1'; | |||
Promise.all([ | |||
.then(function ( | getFileUrl(wrapper.dataset.lq), | ||
getFileUrl(wrapper.dataset.hq) | |||
]).then(function (urls) { | |||
const lqUrl = urls[0] || urls[1]; | |||
const hqUrl = urls[1]; | |||
if (!lqUrl) { | |||
return; | |||
} | |||
wrapper.innerHTML = ''; | |||
const viewer = document.createElement('model-viewer'); | |||
viewer.src = lqUrl; | |||
viewer.setAttribute('camera-controls', ''); | |||
viewer.setAttribute('touch-action', 'pan-y'); | |||
viewer.setAttribute('loading', 'lazy'); | |||
updateViewerSize(viewer, wrapper); | |||
wrapper.appendChild(viewer); | |||
viewer.addEventListener('load', function () { | |||
addQualityButton(wrapper, viewer, lqUrl, hqUrl); | |||
}); | }); | ||
}); | |||
} | |||
function initPlaceholder(wrapper) { | |||
if (wrapper.dataset.initialized) { | |||
return; | |||
} | |||
wrapper.dataset.initialized = '1'; | |||
wrapper.style.position = 'relative'; | |||
const button = document.createElement('button'); | |||
button.type = 'button'; | |||
button.className = 'model-load-button'; | |||
button.innerHTML = | |||
'<span class="model-load-label">▶ Load 3D Model</span>'; | |||
button.addEventListener('click', function () { | |||
loadModel(wrapper); | |||
}); | |||
wrapper.appendChild(button); | |||
} | } | ||
function scan() { | function scan() { | ||
document.querySelectorAll('model- | document | ||
.querySelectorAll('.model-placeholder') | |||
.forEach(initPlaceholder); | |||
} | } | ||
scan(); | scan(); | ||
new MutationObserver(scan).observe(document.body, { | |||
childList: true, | childList: true, | ||
subtree: true | subtree: true | ||
| Line 149: | Line 155: | ||
window.addEventListener('resize', function () { | window.addEventListener('resize', function () { | ||
document.querySelectorAll('model-viewer').forEach(function (viewer) { | document.querySelectorAll('model-viewer').forEach(function (viewer) { | ||
const wrapper = viewer.closest(' | |||
const wrapper = viewer.closest('.model-placeholder'); | |||
if (!wrapper) { | if (!wrapper) { | ||
| Line 158: | Line 166: | ||
updateViewerSize(viewer, wrapper); | updateViewerSize(viewer, wrapper); | ||
const button = | const button = wrapper.querySelector('.mv-quality-toggle'); | ||
if (button) { | if (button) { | ||
updateQualityButtonSize(button, wrapper); | |||
} | } | ||
}); | }); | ||
}); | }); | ||