Commit cd7d98e0 authored by Laureline Nevin's avatar Laureline Nevin ⌨️
Browse files

More petite-vue bindings. Moved pointer events back from viewport to app

parent 49d30b0f
Loading
Loading
Loading
Loading
+82 −80
Changes for index.html: 82 added lines, 80 removed lines.
Original line number Diff line number Diff line
@@ -11,13 +11,13 @@
    </script>
</head>
<body v-scope>
<div class="body-content invisible">
<div class="body-content" v-cloak>
    <h1 class="title" title="Image Viewer with Online Interactive Relighting">IVOIRe</h1>

    <header class="navbar">
        <div>
            <label for="select-dataset">{{t('controls.selected')}}</label>
            <span>{{t('colon')}}</span>
            <label for="select-dataset" v-t="controls.selected"></label>
            <span v-t="colon"></span>
            <select name="dataset" id="select-dataset" class="btn-dark" :disabled="datasetsDisabled"
                    :value="dataset" @change="app.onDatasetSelect($event)">
                <optgroup label="" :label="t('controls.hosted')" class="builtins">
@@ -25,84 +25,82 @@
                </optgroup>
                <optgroup label="" :label="t('controls.inmemory')" class="inmemory">
                    <option v-for="ds in datasets.memory" :value="ds.id">{{loc(ds.name, locale)}}</option>
                    <option class="action" value="create">{{t('controls.createinmemory')}}</option>
                    <option class="action" value="create" v-t="controls.createinmemory"></option>
                </optgroup>
            </select>
            <button id="button-delete-dataset" class="btn-dark" v-show="dataset.startsWith('memory:')"
                    @click="app.deleteMemoryDataset(dataset)">
                {{t('controls.deleteinmemory')}}
            </button>
                    @click="app.deleteMemoryDataset(dataset)" v-t="controls.deleteinmemory"></button>
        </div>
        <div>
            <button class="btn-dark btn-icon" aria-label="Fullscreen" title="Fullscreen" data-icon="fullscreen"
            <button class="btn-dark btn-icon" aria-label="Fullscreen" title="Fullscreen" v-icon="fullscreen"
                    v-show="requestFullscreen" @click="requestFullscreen"></button>
            <select aria-label="Language" class="btn-dark" name="lang"
                    :value="locale" @change="app.setLocale($event.target.value)">
                <option v-for="lang in locales" :value="lang.id">{{lang.name}}</option>
            </select>
            <button class="btn-dark" id="button-help">
                <span>{{t('help.button')}}</span>
                <svg data-icon="help"></svg>
            <button class="btn-dark" @click="$refs.docDialog.showModal()">
                <span v-t="help.button"></span>
                <span v-icon.self="help"></span>
            </button>
        </div>
    </header>

    <div class="controls">
        <label v-show="phase === 'render'" for="select-rendermode"><span>{{t('controls.rendermode')}}</span>
            <span>{{t('colon')}}</span></label>
        <label v-show="phase === 'render'" for="select-rendermode"><span v-t="controls.rendermode"></span>
            <span v-t="colon"></span></label>
        <select v-show="phase === 'render'" name="rendermode" id="select-rendermode">
            <option value="relight">{{t('controls.mode.relight')}}</option>
            <option value="relight_nocolor">{{t('controls.mode.relightnocolor')}}</option>
            <option value="albedo">{{t('controls.mode.albedo')}}</option>
            <option value="normals">{{t('controls.mode.normals')}}</option>
            <option value="relight" v-t="controls.mode.relight"></option>
            <option value="relight_nocolor" v-t="controls.mode.relightnocolor"></option>
            <option value="albedo" v-t="controls.mode.albedo"></option>
            <option value="normals" v-t="controls.mode.normals"></option>
        </select>
        <div class="input-box" v-show="phase === 'render'">
            <label for="input-specular"><span>{{t('controls.specular')}}</span>
                <span>{{t('colon')}}</span>
            <label for="input-specular"><span v-t="controls.specular"></span>
                <span v-t="colon"></span>
                <span class="value"></span>
                <button class="btn-dark btn-icon btn-slim button-input-edit" data-icon="edit" aria-label="Edit value"
                <button class="btn-dark btn-icon btn-slim button-input-edit" v-icon="edit" aria-label="Edit value"
                        title="Edit value"></button>
            </label>
            <input type="range" name="specular" id="input-specular" min="0" max="1" value="0" step=".01"/>
        </div>
        <div class="input-box" v-show="phase === 'render'">
            <label for="input-diffuse"><span>{{t('controls.diffuse')}}</span>
                <span>{{t('colon')}}</span>
            <label for="input-diffuse"><span v-t="controls.diffuse"></span>
                <span v-t="colon"></span>
                <span class="value"></span>
                <button class="btn-dark btn-icon btn-slim button-input-edit" data-icon="edit" aria-label="Edit value"
                <button class="btn-dark btn-icon btn-slim button-input-edit" v-icon="edit" aria-label="Edit value"
                        title="Edit value"></button>
            </label>
            <input type="range" name="diffuse" id="input-diffuse" min="0" max="1" value="0" step=".01"/>
        </div>
        <div class="input-box" v-show="phase === 'render'">
            <label for="input-shine"><span>{{t('controls.shine')}}</span>
                <span>{{t('colon')}}</span>
            <label for="input-shine"><span v-t="controls.shine"></span>
                <span v-t="colon"></span>
                <span class="value"></span>
                <button class="btn-dark btn-icon btn-slim button-input-edit" data-icon="edit" aria-label="Edit value"
                <button class="btn-dark btn-icon btn-slim button-input-edit" v-icon="edit" aria-label="Edit value"
                        title="Edit value"></button>
            </label>
            <input type="range" name="shine" id="input-shine" min="1" max="100" value="1" step="1"/>
        </div>
        <div class="input-box" v-show="phase === 'render'">
            <label for="input-ambiant"><span>{{t('controls.ambiant')}}</span>
                <span>{{t('colon')}}</span>
            <label for="input-ambiant"><span v-t="controls.ambiant"></span>
                <span v-t="colon"></span>
                <span class="value"></span>
                <button class="btn-dark btn-icon btn-slim button-input-edit" data-icon="edit" aria-label="Edit value"
                <button class="btn-dark btn-icon btn-slim button-input-edit" v-icon="edit" aria-label="Edit value"
                        title="Edit value"></button>
            </label>
            <input type="range" name="ambiant" id="input-ambiant" min="0" max="1" value="0" step=".01"/>
        </div>
        <span v-show="phase === 'render'">
            <button class="btn-dark btn-icon" id="button-reset-controls" data-icon="reset"></button>
            <label for="button-reset-controls">{{t('controls.reset')}}</label>
            <button class="btn-dark btn-icon" id="button-reset-controls" v-icon="reset"></button>
            <label for="button-reset-controls" v-t="controls.reset"></label>
        </span>
        <span v-show="phase === 'render'">
            <button class="btn-dark btn-icon" id="button-export" data-icon="export"></button>
            <label for="button-export">{{t('export.button')}}</label>
            <button class="btn-dark btn-icon" @click="fn.exportImage" v-icon="export"></button>
            <label for="button-export" v-t="export.button"></label>
        </span>
        <div class="description-container">
            <div v-if="description">
                <h3>{{t('controls.description')}}</h3>
                <h3 v-t="controls.description"></h3>
                <div class="content">{{ description && loc(description, locale) }}</div>
            </div>
            <pre v-if="output"><code>{{ output }}</code></pre>
@@ -111,19 +109,19 @@
            <canvas id="ivoire-lightball"></canvas>
            <div class="reset-button-container">
                <button class="btn-dark btn-icon" @click="app.resetLightball()"
                        :title="t('controls.resetlightball')" data-icon="reset" v-if="phase==='render'"></button>
                        :title="t('controls.resetlightball')" v-icon="reset" v-if="phase==='render'"></button>
            </div>
        </div>
    </div>

    <main id="app">
        <div class="view-controls">
            <button class="btn-dark btn-icon" id="button-zoom-fit" :title="t('controls.fitview')"
                    data-icon="zoom-fit"></button>
            <button class="btn-dark btn-icon" id="button-zoom-vfit" :title="t('controls.fitviewv')"
                    data-icon="zoom-vfit"></button>
            <button class="btn-dark btn-icon" id="button-zoom-hfit" :title="t('controls.fitviewh')"
                    data-icon="zoom-hfit"></button>
            <button class="btn-dark btn-icon" :title="t('controls.fitview')" @click="zoomFit()"
                    v-icon="zoom-fit"></button>
            <button class="btn-dark btn-icon" :title="t('controls.fitviewv')" @click="zoomFit('v')"
                    v-icon="zoom-vfit"></button>
            <button class="btn-dark btn-icon" :title="t('controls.fitviewh')" @click="zoomFit('h')"
                    v-icon="zoom-hfit"></button>
        </div>
        <canvas id="ivoire-display"></canvas>
        <progress aria-label="Downloading data" id="load-progress" class="hidden" max="100"></progress>
@@ -131,42 +129,46 @@
    </main>
</div>

<dialog id="message" class="drop-shadow" @click="app.onDialogClick">
<dialog id="message" class="drop-shadow" ref="messageDialog" @click="app.onDialogClick">
    <h1></h1>
    <p></p>
    <button class="btn-dark" type="reset" autofocus @click="$el.parent.close()">{{t('ok')}}</button>
    <button class="btn-dark" type="reset" autofocus @click="$refs.messageDialog.close()" v-t="ok"></button>
</dialog>
<dialog id="create-inmemory" class="drop-shadow" @click="app.onDialogClick">
    <h1>{{t('memcreate.title')}}</h1>
<dialog id="create-inmemory" ref="memCreateDia" class="drop-shadow" @click="app.onDialogClick"
        @close="fn.cancelCreateMemoryDataset($el.returnValue)">
    <h1 v-t="memcreate.title"></h1>
    <form action="#">
        <label for="upload-dataset-name" autofocus>
            <span>{{t('memcreate.name')}}</span>
            <span>{{t('colon')}}</span>&nbsp;</label>
            <span v-t="memcreate.name"></span>
            <span v-t="colon"></span>&nbsp;</label>
        <input type="text" name="dataset-name" id="upload-dataset-name" placeholder="In-memory" size="50"/>
        <label for="upload-color-image">
            <span>{{t('memcreate.colorimg')}}</span>
            <span>{{t('colon')}}</span>&nbsp;</label>
        <input type="file" name="color-image" id="upload-color-image"/>
            <span v-t="memcreate.colorimg"></span>
            <span v-t="colon"></span>&nbsp;</label>
        <input type="file" name="color-image" id="upload-color-image" @change="fn.onCreateMemoryFileInput"/>
        <label for="upload-normals-image">
            <span>{{t('memcreate.normalsimg')}}</span>
            <span>{{t('colon')}}</span>&nbsp;</label>
            <span v-t="memcreate.normalsimg"></span>
            <span v-t="colon"></span>&nbsp;</label>
        <input type="file" name="normals-image" id="upload-normals-image"/>
    </form>
    <p>{{t('memcreate.notice')}}</p>
    <button class="btn" type="reset">{{t('cancel')}}</button>
    <button class="btn" type="submit">{{t('memcreate.create')}}</button>
    <p v-t="memcreate.notice"></p>
    <button class="btn" type="reset" v-t="cancel" @click="console.log($refs), $refs.memCreateDia.close()"></button>
    <button class="btn" type="submit" v-t="memcreate.create"
            @click="fn.submitCreateMemoryDataset($event, $refs.memCreateDia)"></button>
</dialog>
<dialog id="export-success" @click="app.onDialogClick">
    <h3>{{t('export.success')}}</h3>
    <img src="" alt="Exported image">
<dialog id="export-success" ref="exportDialog" @click="app.onDialogClick"
        @close="fn.onExportDialogClose($refs.exportImg)">
    <h3 v-t="export.success"></h3>
    <img src="" alt="Exported image" ref="exportImg">
    <div>
        <button class="btn" id="button-download" autofocus>{{t('export.download')}}</button>
        <button class="btn" type="reset">{{t('export.close')}}</button>
        <button class="btn" id="button-download" autofocus v-t="export.download"
                @click="fn.downloadExportImage($refs.exportImg, $refs.exportDialog)"></button>
        <button class="btn" type="reset" v-t="export.close" @click="$refs.exportDialog.close()"></button>
    </div>
    <a href="" id="export-download-anchor" class="hidden"></a>
</dialog>
<dialog id="documentation" @click="app.onDialogClick">
    <button type="reset" class="btn-close btn-icon" data-icon="close"></button>
<dialog id="documentation" @click="app.onDialogClick" ref="docDialog">
    <button type="reset" class="btn-close btn-icon" v-icon="close" @click="$refs.docDialog.close()"></button>
    <div class="logos">
        <a target="_blank" href="https://www.greyc.fr">
            <img src="" :src="t('help.logos.greyc')" alt="GREYC logo"></a>
@@ -175,28 +177,28 @@
        <a target="_blank" href="https://unicaen.fr"><img src="/images/unicaen.svg" alt="Unicaen logo"></a>
    </div>
    <div class="content">
        <h2 v-html="t('help.about.title')"></h2>
        <p v-html="t('help.about.text')"></p>
        <h2 v-t.raw="help.about.title"></h2>
        <p v-t.raw="help.about.text"></p>

        <h3 v-html="t('help.howitworks.title')"></h3>
        <p v-html="t('help.howitworks.text')"></p>
        <h3 v-t.raw="help.howitworks.title"></h3>
        <p v-t.raw="help.howitworks.text"></p>

        <h2 v-html="t('help.howto.title')"></h2>
        <p v-html="t('help.howto.text')"></p>
        <h2 v-t.raw="help.howto.title"></h2>
        <p v-t.raw="help.howto.text"></p>
        <dl>
            <dt v-html="t('controls.rendermode')"></dt>
            <dd v-html="t('help.rendermode')"></dd>
            <dt v-html="t('controls.ambiant')"></dt>
            <dd v-html="t('help.ambiant')"></dd>
            <dt v-html="t('controls.diffuse')"></dt>
            <dd v-html="t('help.diffuse')"></dd>
            <dt v-html="t('controls.specular')"></dt>
            <dd v-html="t('help.specular')"></dd>
            <dt v-html="t('controls.shine')"></dt>
            <dd v-html="t('help.shine')"></dd>
            <dt v-t.raw="controls.rendermode"></dt>
            <dd v-t.raw="help.rendermode"></dd>
            <dt v-t.raw="controls.ambiant"></dt>
            <dd v-t.raw="help.ambiant"></dd>
            <dt v-t.raw="controls.diffuse"></dt>
            <dd v-t.raw="help.diffuse"></dd>
            <dt v-t.raw="controls.specular"></dt>
            <dd v-t.raw="help.specular"></dd>
            <dt v-t.raw="controls.shine"></dt>
            <dd v-t.raw="help.shine"></dd>
        </dl>
        <h3 v-html="t('help.export.title')"></h3>
        <p v-html="t('help.export.text')"></p>
        <h3 v-t.raw="help.export.title"></h3>
        <p v-t.raw="help.export.text"></p>
    </div>
</dialog>
<script type="module" src="/src/main.ts"></script>
+165 −80

File changed.

Preview size limit exceeded, changes collapsed.

+0 −1
Changes for src/download.ts: 0 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -134,7 +134,6 @@ export class DownloadManager {
            ...DEFAULT_OPTIONS,
            ...par
        }
        console.debug(`Loading: "${url}", expected: "${expected}"`);
        return this.withProgressBar<ResponseTypes[T]>((progress) => new Promise((res, rej) => {
            xhr.addEventListener("loadend", (e) => {
                progress(e.total, e.total);
+23 −7
Changes for src/main.ts: 23 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -23,12 +23,28 @@ for (const el of document.querySelectorAll('*[data-icon]')) {

const app = new App({ en, fr });

createApp(app.rx)
    .directive('v-html', ({ el, get, effect }) => {
const vApp = createApp(app.rx);
vApp.directive('icon', ({ el, exp, modifiers, effect }) => {
    effect(() => {
            el.innerHTML = get();
        if (!exp) throw new Error();
        const content = iconTpl.content.cloneNode(true) as HTMLElement;
        const useTag = content.querySelector('use')!;
        useTag.setAttribute('href', useTag.getAttribute('href')!.replace('{{icon}}', exp));
        if (modifiers && modifiers.self) {
            el.replaceWith(content);
        } else {
            el.replaceChildren(content);
        }
    });
    })
    .mount();

document.querySelector('.body-content')!.classList.remove('invisible');
});
vApp.directive('t', ({ el, exp, modifiers, effect }) => {
    effect(() => {
        const content = app.rx.t(exp);
        if (modifiers && modifiers.raw) {
            el.innerHTML = content;
        } else {
            el.textContent = content;
        }
    });
});
vApp.mount();
+2 −1
Changes for src/style.sass: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ dialog

	&#message
		background: darkslateblue
		color: white
		padding: 1rem
		border-radius: 1rem
		max-width: 80%
@@ -229,7 +230,7 @@ dialog
.hidden
	display: none !important

.invisible
*[v-cloak]
	visibility: hidden !important


Loading