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:
@@ -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()
|
||||
Reference in New Issue
Block a user