1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
<template>
<iframe ref="iframe" :src="iframeUrl" class="pdfjs-viewer-iframe" @load="onIframeLoad"/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { getLocale } from '../../assets/javascripts/lib/gettext';
interface PdfJsIframe {
contentWindow: {
setStudipUser(formattedName: string): void;
PDFViewerApplication: {
pdfDocument: {
saveDocument(): Promise<BlobPart>;
};
};
PDFViewerApplicationOptions: {
set(field: string, value: unknown): void;
setAll(options: Record<string, unknown>): void;
};
};
}
export default defineComponent({
props: {
file_id: {
type: String,
required: true,
},
userFullname: {
type: String,
required: true
}
},
computed: {
iframeUrl(): string {
return window.STUDIP.URLHelper.getURL('assets/javascripts/pdfjs/web/viewer.html', {
file: window.STUDIP.URLHelper.getURL('sendfile.php', { file_id: this.file_id }),
});
},
},
mounted() {
// This is an event dispatched by PDF.js from within the iframe which
// grants us an opportunity to set configuration values before PDF.js
// is initialized.
// See webViewerLoad() in pdfjs/web/viewer.js.
window.document.addEventListener('webviewerloaded', this.onWebViewerLoaded);
// Add an event listener for dialog closing so that we can prompt the user
// before potentially losing data.
$('.studip-dialog').on('dialogbeforeclose', this.beforeDialogClose);
},
unmounted() {
window.document.removeEventListener('webviewerloaded', this.onWebViewerLoaded);
},
methods: {
async savePdf(): Promise<Blob> {
const data = await (
this.$refs.iframe as unknown as PdfJsIframe
).contentWindow.PDFViewerApplication.pdfDocument.saveDocument();
return new Blob([data], { type: 'application/pdf' });
},
beforeDialogClose(evt: Event) {
if (!window.confirm(this.$gettext('Ihre Änderungen wurden noch nicht gespeichert.'))) {
evt.preventDefault();
evt.stopPropagation();
return false;
}
return true;
},
onWebViewerLoaded(evt: Event) {
const iframe = this.$refs.iframe as unknown as PdfJsIframe;
// Verify that the event is from our iframe, because there could be
// multiple PdfJsViewer components on the same page.
if ((evt as CustomEvent).detail.source === iframe.contentWindow) {
const locale = getLocale()
// Stud.IP uses '_' and PDF.js uses '-' (e.g. 'de_DE', 'de-DE').
.replace('_', '-');
const options = {
'localeProperties': {
lang: locale,
},
// Disable 'User Preferences' in PDF.js so they will not
// conflict with Stud.IP-based configuration.
'disablePreferences': true,
'viewerCssTheme': 1
};
iframe.contentWindow.PDFViewerApplicationOptions.setAll(options);
}
},
// Get the name of the current user and set it in PDF.js's options so that
// it can be applied to the annotations they create and edit.
async onIframeLoad(event: Event): Promise<void> {
(this.$refs.iframe as unknown as PdfJsIframe).contentWindow.setStudipUser(
this.userFullname
);
},
},
});
</script>
<style scoped>
.pdfjs-viewer-iframe {
width: 100%;
height: 100vh;
}
</style>
|