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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
<template>
<div class="writer" :style="composerStyle">
<studip-icon shape="blubber" :size="30" role="info"></studip-icon>
<label for="blubber-placeholder" class="sr-only">
{{ placeholder || $gettext('Schreib was, frag was. Enter zum Abschicken.') }}
</label>
<textarea
:placeholder="placeholder || $gettext('Schreib was, frag was. Enter zum Abschicken.')"
v-model="localText"
@change="saveCommentToSession"
@focus="resizeTextarea"
@keydown.enter.exact="submit"
@keyup.up.exact="editPreviousComment"
@keyup="saveCommentToSession"
ref="textarea"
id="blubber-placeholder"
></textarea>
<a class="send" @click="submit" :title="$gettext('Abschicken')">
<studip-icon shape="arr_2up" :size="30"></studip-icon>
</a>
<label class="upload" :title="$gettext('Datei hochladen')" tabindex="0" ref="label" @keydown="simulateClick">
<input type="file" multiple style="display: none" @change="onFilesPick" />
<studip-icon shape="upload" :size="30"></studip-icon>
</label>
</div>
</template>
<script>
export default {
name: 'blubber-composer',
model: {
prop: 'text',
event: 'change',
},
props: {
placeholder: {
type: String,
default: '',
},
progress: {
type: Number,
default: 0,
},
text: {
type: String,
default: '',
},
},
data: () => ({
localText: '',
}),
computed: {
composerStyle() {
return {
'background-size': `${this.progress}%`,
};
},
},
methods: {
editPreviousComment() {
this.$emit('edit-previous');
},
focusTextarea() {
this.$refs.textarea.focus();
this.$refs.textarea.setSelectionRange(0, 0);
},
onFilesPick(event) {
let files =
event.dataTransfer !== undefined
? event.dataTransfer.files // file drop
: event.target.files; // upload button
this.$emit('pick-files', files);
},
reset() {
this.localText = '';
},
resizeTextarea() {
const { textarea } = this.$refs;
const style = window.getComputedStyle(textarea, null);
let heightOffset;
if (style.boxSizing === 'content-box') {
heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
} else {
heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
}
if (isNaN(heightOffset)) {
heightOffset = 0;
}
textarea.style.height = '';
textarea.style.height = (textarea.scrollHeight + heightOffset) + 'px';
},
simulateClick(event) {
if (event.code === 'Enter') {
this.$refs.label.click();
}
},
submit(event) {
const text = this.localText;
this.reset();
if (text.trim().length === 0) {
return false;
}
event.preventDefault();
this.$emit('add-posting', text);
},
saveCommentToSession() {
this.resizeTextarea();
this.$emit('change', this.localText);
},
},
mounted() {
this.localText = this.text;
this.$nextTick(() => {
this.resizeTextarea();
});
},
watch: {
text(newText, oldText) {
if (this.localText !== newText) {
this.localText = newText;
this.focusTextarea();
}
},
},
};
</script>
|