mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-14 05:57:32 -07:00
✌️
This commit is contained in:
parent
1460259990
commit
668a249e42
5 changed files with 43 additions and 29 deletions
|
@ -78,6 +78,7 @@
|
||||||
"@types/websocket": "0.0.37",
|
"@types/websocket": "0.0.37",
|
||||||
"accesses": "2.5.0",
|
"accesses": "2.5.0",
|
||||||
"animejs": "2.2.0",
|
"animejs": "2.2.0",
|
||||||
|
"autosize": "4.0.0",
|
||||||
"autwh": "0.0.1",
|
"autwh": "0.0.1",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"body-parser": "1.18.2",
|
"body-parser": "1.18.2",
|
||||||
|
|
|
@ -22,7 +22,7 @@ import * as pictograph from 'pictograph';
|
||||||
import contains from '../../../common/scripts/contains';
|
import contains from '../../../common/scripts/contains';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
props: ['type', 'q', 'textarea', 'complete', 'close'],
|
props: ['type', 'q', 'textarea', 'complete', 'close', 'x', 'y'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
fetching: true,
|
fetching: true,
|
||||||
|
@ -37,6 +37,27 @@ export default Vue.extend({
|
||||||
return (this.$refs.suggests as Element).children;
|
return (this.$refs.suggests as Element).children;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updated() {
|
||||||
|
//#region 位置調整
|
||||||
|
const margin = 32;
|
||||||
|
|
||||||
|
if (this.x + this.$el.offsetWidth > window.innerWidth - margin) {
|
||||||
|
this.$el.style.left = (this.x - this.$el.offsetWidth) + 'px';
|
||||||
|
this.$el.style.marginLeft = '-16px';
|
||||||
|
} else {
|
||||||
|
this.$el.style.left = this.x + 'px';
|
||||||
|
this.$el.style.marginLeft = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.y + this.$el.offsetHeight > window.innerHeight - margin) {
|
||||||
|
this.$el.style.top = (this.y - this.$el.offsetHeight) + 'px';
|
||||||
|
this.$el.style.marginTop = '0';
|
||||||
|
} else {
|
||||||
|
this.$el.style.top = this.y + 'px';
|
||||||
|
this.$el.style.marginTop = 'calc(1em + 8px)';
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.textarea.addEventListener('keydown', this.onKeydown);
|
this.textarea.addEventListener('keydown', this.onKeydown);
|
||||||
|
|
||||||
|
@ -136,7 +157,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.mk-autocomplete
|
.mk-autocomplete
|
||||||
position absolute
|
position fixed
|
||||||
z-index 65535
|
z-index 65535
|
||||||
margin-top calc(1em + 8px)
|
margin-top calc(1em + 8px)
|
||||||
overflow hidden
|
overflow hidden
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mk-messaging-form">
|
<div class="mk-messaging-form">
|
||||||
<textarea v-model="text" @keypress="onKeypress" @paste="onPaste" placeholder="%i18n:common.input-message-here%" v-autocomplete></textarea>
|
<textarea v-model="text" ref="textarea" @keypress="onKeypress" @paste="onPaste" placeholder="%i18n:common.input-message-here%" v-autocomplete></textarea>
|
||||||
<div class="file" v-if="file">{{ file.name }}</div>
|
<div class="file" v-if="file">{{ file.name }}</div>
|
||||||
<mk-uploader ref="uploader"/>
|
<mk-uploader ref="uploader"/>
|
||||||
<button class="send" @click="send" :disabled="sending" title="%i18n:common.send%">
|
<button class="send" @click="send" :disabled="sending" title="%i18n:common.send%">
|
||||||
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import * as autosize from 'autosize';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
props: ['user'],
|
props: ['user'],
|
||||||
data() {
|
data() {
|
||||||
|
@ -27,6 +29,9 @@ export default Vue.extend({
|
||||||
sending: false
|
sending: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
autosize(this.$refs.textarea);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onPaste(e) {
|
onPaste(e) {
|
||||||
const data = e.clipboardData;
|
const data = e.clipboardData;
|
||||||
|
@ -93,6 +98,7 @@ export default Vue.extend({
|
||||||
height 64px
|
height 64px
|
||||||
margin 0
|
margin 0
|
||||||
padding 8px
|
padding 8px
|
||||||
|
resize none
|
||||||
font-size 1em
|
font-size 1em
|
||||||
color #000
|
color #000
|
||||||
outline none
|
outline none
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
</div>
|
</div>
|
||||||
<footer>
|
<footer>
|
||||||
<div ref="notifications" class="notifications"></div>
|
<div ref="notifications" class="notifications"></div>
|
||||||
<div class="grippie" title="%i18n:common.tags.mk-messaging-room.resize-form%"></div>
|
|
||||||
<x-form :user="user"/>
|
<x-form :user="user"/>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
@ -316,16 +315,4 @@ export default Vue.extend({
|
||||||
line-height 32px
|
line-height 32px
|
||||||
font-size 16px
|
font-size 16px
|
||||||
|
|
||||||
> .grippie
|
|
||||||
height 10px
|
|
||||||
margin-top -10px
|
|
||||||
background transparent
|
|
||||||
cursor ns-resize
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
//background rgba(0, 0, 0, 0.1)
|
|
||||||
|
|
||||||
&:active
|
|
||||||
//background rgba(0, 0, 0, 0.2)
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -82,6 +82,15 @@ class Autocomplete {
|
||||||
// 既に開いているサジェストは閉じる
|
// 既に開いているサジェストは閉じる
|
||||||
this.close();
|
this.close();
|
||||||
|
|
||||||
|
//#region サジェストを表示すべき位置を計算
|
||||||
|
const caretPosition = getCaretCoordinates(this.textarea, this.textarea.selectionStart);
|
||||||
|
|
||||||
|
const rect = this.textarea.getBoundingClientRect();
|
||||||
|
|
||||||
|
const x = rect.left + caretPosition.left - this.textarea.scrollLeft;
|
||||||
|
const y = rect.top + caretPosition.top - this.textarea.scrollTop;
|
||||||
|
//#endregion
|
||||||
|
|
||||||
// サジェスト要素作成
|
// サジェスト要素作成
|
||||||
this.suggestion = new MkAutocomplete({
|
this.suggestion = new MkAutocomplete({
|
||||||
propsData: {
|
propsData: {
|
||||||
|
@ -89,22 +98,12 @@ class Autocomplete {
|
||||||
complete: this.complete,
|
complete: this.complete,
|
||||||
close: this.close,
|
close: this.close,
|
||||||
type: type,
|
type: type,
|
||||||
q: q
|
q: q,
|
||||||
|
x,
|
||||||
|
y
|
||||||
}
|
}
|
||||||
}).$mount();
|
}).$mount();
|
||||||
|
|
||||||
//#region サジェストを表示すべき位置を計算
|
|
||||||
const caretPosition = getCaretCoordinates(this.textarea, this.textarea.selectionStart);
|
|
||||||
|
|
||||||
const rect = this.textarea.getBoundingClientRect();
|
|
||||||
|
|
||||||
const x = rect.left + window.pageXOffset + caretPosition.left - this.textarea.scrollLeft;
|
|
||||||
const y = rect.top + window.pageYOffset + caretPosition.top - this.textarea.scrollTop;
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
this.suggestion.$el.style.left = x + 'px';
|
|
||||||
this.suggestion.$el.style.top = y + 'px';
|
|
||||||
|
|
||||||
// 要素追加
|
// 要素追加
|
||||||
document.body.appendChild(this.suggestion.$el);
|
document.body.appendChild(this.suggestion.$el);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue