Refactor js files (#48)

This pr is a significant reorg of the js files.

1) All non-basic functions have been moved out of the main glmv.js
2) 'Metadata' has been universally changed to mvconfig to avoid conflict with actual file metadata
3) Configuration changing functions have been split off into glmv-mvconfig.js
4) Hotspot modification functions have been split off into glmv-hs.js

Reviewed-on: #48
This commit is contained in:
2024-11-18 03:54:29 +00:00
parent d419f6fe7e
commit 0dd9aba2b6
5 changed files with 677 additions and 616 deletions

View File

@@ -1,195 +1,282 @@
let [_, origMetadata] = extractMetadata()
//Initialize globals
require('./glmv-mvconfig.js')
require('./glmv-hs.js')
//Annotation Edit Controls
const addHS = new OO.ui.ButtonWidget({
icon: 'mapPinAdd',
label: 'Add annotation',
invisibleLabel: true,
class: 'edit-button'
})
addHS.on('click', readyAddHotspot)
addHS.setDisabled(true)
/**
* Use the OOui js library to create wikis-style menu
* options on the preview edits page for interaction
* with the model
*/
buildPreviewMenu = function() {
let [_, origMetadata] = extractMvconfig()
const updateHS = new OO.ui.ButtonWidget({
icon: 'reload',
label: 'Update annotations',
invisibleLabel: true
})
updateHS.on('click', readMetadata)
updateHS.setDisabled(true)
//Annotation Edit Controls
const addHS = new OO.ui.ButtonWidget({
icon: 'mapPinAdd',
label: 'Add annotation',
invisibleLabel: true,
class: 'edit-button'
})
addHS.on('click', readyAddHotspot)
addHS.setDisabled(true)
const deleteHS = new OO.ui.ButtonWidget({
icon: 'cancel',
label: 'Delete annotation',
invisibleLabel: true
})
deleteHS.on('click', readyDelHotspot)
deleteHS.setDisabled(true)
const updateHS = new OO.ui.ButtonWidget({
icon: 'reload',
label: 'Update annotations',
invisibleLabel: true
})
updateHS.on('click', readMvconfig)
updateHS.setDisabled(true)
const setOptions = ['default', ...Object.keys(origMetadata.annotationSets)]
let setOptionItems = []
setOptions.forEach(opt => {
setOptionItems.push(new OO.ui.MenuOptionWidget({data: opt, label: opt}))
})
const deleteHS = new OO.ui.ButtonWidget({
icon: 'cancel',
label: 'Delete annotation',
invisibleLabel: true
})
deleteHS.on('click', readyDelHotspot)
deleteHS.setDisabled(true)
const setSelectHS = new OO.ui.ButtonMenuSelectWidget({
icon: 'mapTrail',
label: 'Select annotation set',
invisibleLabel: true,
menu: {
items: setOptionItems,
width: 'min-content'
},
$overlay: $('#bodyContent')
})
setSelectHS.getMenu().on( 'choose', selSet => {
selectAnnotationSet(selSet.data)
})
setSelectHS.setDisabled(true)
const setOptions = ['default', ...Object.keys(origMetadata.annotationSets)]
let setOptionItems = []
setOptions.forEach(opt => {
setOptionItems.push(new OO.ui.MenuOptionWidget({data: opt, label: opt}))
})
const hotspotButtons = new OO.ui.ButtonGroupWidget({
items: [ addHS, updateHS, deleteHS, setSelectHS ]
})
const setSelectHS = new OO.ui.ButtonMenuSelectWidget({
icon: 'mapTrail',
label: 'Select annotation set',
invisibleLabel: true,
menu: {
items: setOptionItems,
width: 'min-content'
},
$overlay: $('#bodyContent')
})
setSelectHS.getMenu().on( 'choose', selSet => {
selectAnnotationSet(selSet.data)
})
setSelectHS.setDisabled(true)
//View Edit Controls
const downloadViewerImage = new OO.ui.ButtonWidget({
icon: 'imageAdd',
label: 'Download current image',
invisibleLabel: true
})
downloadViewerImage.on('click', () => {
downloadImage(mw.config.values.wgTitle)
})
downloadViewerImage.setDisabled(true)
const hotspotButtons = new OO.ui.ButtonGroupWidget({
items: [ addHS, updateHS, deleteHS, setSelectHS ]
})
const setView = new OO.ui.ButtonWidget({
icon: 'camera',
label: 'Set Initial View',
invisibleLabel: true
})
setView.on('click', writeCameraOrbit)
setView.setDisabled(true)
//View Edit Controls
const downloadViewerImage = new OO.ui.ButtonWidget({
icon: 'imageAdd',
label: 'Download current image',
invisibleLabel: true
})
downloadViewerImage.on('click', () => {
downloadImage(mw.config.values.wgTitle)
})
downloadViewerImage.setDisabled(true)
const setControl = new OO.ui.ButtonWidget({
icon: 'hand',
label: 'Toggle camera control',
invisibleLabel: true
})
setControl.on('click', () => $('model-viewer')[0].toggleAttribute('camera-controls', toggleCameraControl()))
setControl.setDisabled(true)
const setView = new OO.ui.ButtonWidget({
icon: 'camera',
label: 'Set Initial View',
invisibleLabel: true
})
setView.on('click', writeCameraOrbit)
setView.setDisabled(true)
//View Limit Controls
const setMinYaw = new OO.ui.ButtonWidget({
label: 'Min'
})
setMinYaw.on('click', () => {
writeCameraLimit('yaw','min')
})
const setControl = new OO.ui.ButtonWidget({
icon: 'hand',
label: 'Toggle camera control',
invisibleLabel: true
})
setControl.on('click', () => $('model-viewer')[0].toggleAttribute('camera-controls', toggleCameraControl()))
setControl.setDisabled(true)
const setMaxYaw = new OO.ui.ButtonWidget({
label: 'Max'
})
setMaxYaw.on('click', () => {
writeCameraLimit('yaw','max')
})
//View Limit Controls
const setMinYaw = new OO.ui.ButtonWidget({
label: 'Min'
})
setMinYaw.on('click', () => {
writeCameraLimit('yaw','min')
})
const yawLimitButtons = new OO.ui.ButtonGroupWidget({
items: [ setMinYaw, setMaxYaw ]
})
const setMaxYaw = new OO.ui.ButtonWidget({
label: 'Max'
})
setMaxYaw.on('click', () => {
writeCameraLimit('yaw','max')
})
const labelYaw = new OO.ui.LabelWidget({
label: "Yaw:"
})
const yawLimitButtons = new OO.ui.ButtonGroupWidget({
items: [ setMinYaw, setMaxYaw ]
})
const yawButtons = new OO.ui.HorizontalLayout({
items: [
labelYaw,
yawLimitButtons
],
id: 'yaw-limits'
})
const labelYaw = new OO.ui.LabelWidget({
label: "Yaw:"
})
const setMinPitch = new OO.ui.ButtonWidget({
label: 'Min'
})
setMinPitch.on('click', () => {
writeCameraLimit('pitch','min')
})
const yawButtons = new OO.ui.HorizontalLayout({
items: [
labelYaw,
yawLimitButtons
],
id: 'yaw-limits'
})
const setMaxPitch = new OO.ui.ButtonWidget({
label: 'Max'
})
setMaxPitch.on('click', () => {
writeCameraLimit('pitch','max')
})
const setMinPitch = new OO.ui.ButtonWidget({
label: 'Min'
})
setMinPitch.on('click', () => {
writeCameraLimit('pitch','min')
})
const pitchLimitButtons = new OO.ui.ButtonGroupWidget({
items: [ setMinPitch, setMaxPitch ]
})
const setMaxPitch = new OO.ui.ButtonWidget({
label: 'Max'
})
setMaxPitch.on('click', () => {
writeCameraLimit('pitch','max')
})
const labelPitch = new OO.ui.LabelWidget({
label: "Pitch:"
})
const pitchLimitButtons = new OO.ui.ButtonGroupWidget({
items: [ setMinPitch, setMaxPitch ]
})
const pitchButtons = new OO.ui.HorizontalLayout({
items: [
labelPitch,
pitchLimitButtons
],
id: 'pitch-limits'
})
const labelPitch = new OO.ui.LabelWidget({
label: "Pitch:"
})
const setLims = new OO.ui.PopupButtonWidget({
label: 'Set View Limits',
invisibleLabel: true,
icon: 'tableMergeCells',
popup: {
$content: yawButtons.$element.add(pitchButtons.$element),
padded: true,
position: 'above'
},
$overlay: $('#bodyContent')
})
setLims.setDisabled(true)
const pitchButtons = new OO.ui.HorizontalLayout({
items: [
labelPitch,
pitchLimitButtons
],
id: 'pitch-limits'
})
const setViewConfig = [...Object.keys(origMetadata.viewerConfig)]
let setViewItems = []
setViewConfig.forEach(opt => {
setViewItems.push(new OO.ui.MenuOptionWidget({data: opt, label: opt}))
})
const setLims = new OO.ui.PopupButtonWidget({
label: 'Set View Limits',
invisibleLabel: true,
icon: 'tableMergeCells',
popup: {
$content: yawButtons.$element.add(pitchButtons.$element),
padded: true,
position: 'above'
},
$overlay: $('#bodyContent')
})
setLims.setDisabled(true)
const selectVC = new OO.ui.ButtonMenuSelectWidget({
icon: 'eye',
label: 'Select view configuration',
invisibleLabel: true,
menu: {
items: setViewItems,
width: 'min-content'
},
$overlay: $('#bodyContent')
})
selectVC.getMenu().on( 'choose', selSet => {
selectViewConfig(selSet.data)
})
selectVC.setDisabled(true)
const setViewConfig = [...Object.keys(origMetadata.viewerConfig)]
let setViewItems = []
setViewConfig.forEach(opt => {
setViewItems.push(new OO.ui.MenuOptionWidget({data: opt, label: opt}))
})
const cameraButtons = new OO.ui.ButtonGroupWidget({
items: [ downloadViewerImage, setControl, setView, setLims, selectVC ]
})
const selectVC = new OO.ui.ButtonMenuSelectWidget({
icon: 'eye',
label: 'Select view configuration',
invisibleLabel: true,
menu: {
items: setViewItems,
width: 'min-content'
},
$overlay: $('#bodyContent')
})
selectVC.getMenu().on( 'choose', selSet => {
selectViewConfig(selSet.data)
})
selectVC.setDisabled(true)
//Main Menu
const modelMenu = new OO.ui.HorizontalLayout({
items: [
hotspotButtons,
cameraButtons
],
id: 'edit-model-menu'
})
const cameraButtons = new OO.ui.ButtonGroupWidget({
items: [ downloadViewerImage, setControl, setView, setLims, selectVC ]
})
$('#wikiPreview').after(modelMenu.$element)
//Main Menu
const modelMenu = new OO.ui.HorizontalLayout({
items: [
hotspotButtons,
cameraButtons
],
id: 'edit-model-menu'
})
$('#wikiPreview').after(modelMenu.$element)
return [modelMenu, selectVC]
}
/**
* Enable all the preview menu widgets (called by
* model load event)
*/
enableMenu = function() {
modelMenu.items.forEach(group => {
group.items.forEach(el => el.setDisabled(false))
});
}
}
/**
* Add a selection option to a ButtonMenuSelectWidget
*
* @param {ButtonMenuSelectWidget} menuWidget
*/
addMenuOption = function(menuWidget) {
menuWidget.menu.addItems([new OO.ui.MenuOptionWidget({data: 'New option', label: 'New option'})])
}
/**
* Disable general interaction with model
* viewer for specific additional function
*
* @param {string} fnClass class to add to model-viewer
* @param {callback} viewCall callback function to add to model-viewer
* @return {Element} model-viewer element
*/
disableViewer = function(fnClass, viewCall) {
const previewMv = $('model-viewer')
if (viewCall) previewMv.one('click', viewCall)
if (fnClass) previewMv.addClass(fnClass)
previewMv[0].disableTap = true
previewMv[0].toggleAttribute('camera-controls', false)
return previewMv[0]
}
/**
* Enable general interaction with model
* viewer
*
* @return {Element} model-viewer element
*/
enableViewer = function() {
const previewMv = $('model-viewer')
previewMv.off('click', clickAddHotspot)
previewMv.off('click', cancelDeleteHotspot)
previewMv.removeClass('AddingHotspot DeletingHotspot')
previewMv[0].disableTap = false
previewMv[0].toggleAttribute('camera-controls', true)
return previewMv[0]
}
/**
* Use the model viewer methods to get image
* of current view and download
*
* @param {string} defName wiki page name to use as base file name
*/
downloadImage = function(defName) {
const imgName = defName.split('.')[0]
const mView = $('model-viewer')[0]
const dlA = document.createElement('a')
dlA.setAttribute('download',imgName + '.png')
const reader = new FileReader()
reader.addEventListener("load", () => {
dlA.setAttribute('href',reader.result)
dlA.click()
},{once: true})
mView.toBlob(null, null, true)
.then(imgBlob => {
reader.readAsDataURL(imgBlob)
})
}
//Initialize the menu and get required global objects
const [modelMenu, viewSelector] = buildPreviewMenu()