Improve drag and drop
This commit is contained in:
parent
56bef13850
commit
c6118c7bc8
7 changed files with 148 additions and 154 deletions
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mk-messaging-form"
|
<div class="mk-messaging-form"
|
||||||
@dragover.prevent.stop="onDragover"
|
@dragover.stop="onDragover"
|
||||||
@drop.prevent.stop="onDrop"
|
@drop.stop="onDrop"
|
||||||
>
|
>
|
||||||
<textarea
|
<textarea
|
||||||
v-model="text"
|
v-model="text"
|
||||||
|
@ -89,34 +89,33 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
onDragover(e) {
|
onDragover(e) {
|
||||||
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||||
|
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
||||||
|
if (isFile || isDriveFile) {
|
||||||
|
e.preventDefault();
|
||||||
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onDrop(e): void {
|
onDrop(e): void {
|
||||||
// ファイルだったら
|
// ファイルだったら
|
||||||
if (e.dataTransfer.files.length == 1) {
|
if (e.dataTransfer.files.length == 1) {
|
||||||
|
e.preventDefault();
|
||||||
this.upload(e.dataTransfer.files[0]);
|
this.upload(e.dataTransfer.files[0]);
|
||||||
return;
|
return;
|
||||||
} else if (e.dataTransfer.files.length > 1) {
|
} else if (e.dataTransfer.files.length > 1) {
|
||||||
|
e.preventDefault();
|
||||||
alert('メッセージに添付できるのはひとつのファイルのみです');
|
alert('メッセージに添付できるのはひとつのファイルのみです');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// データ取得
|
//#region ドライブのファイル
|
||||||
const data = e.dataTransfer.getData('text');
|
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
||||||
if (data == null) return;
|
if (driveFile != null && driveFile != '') {
|
||||||
|
this.file = JSON.parse(driveFile);
|
||||||
try {
|
e.preventDefault();
|
||||||
// パース
|
|
||||||
const obj = JSON.parse(data);
|
|
||||||
|
|
||||||
// (ドライブの)ファイルだったら
|
|
||||||
if (obj.type == 'file') {
|
|
||||||
this.file = obj.file;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// not a json, so noop
|
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
},
|
},
|
||||||
|
|
||||||
onKeypress(e) {
|
onKeypress(e) {
|
||||||
|
|
|
@ -88,7 +88,14 @@ export default Vue.extend({
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onDragover(e) {
|
onDragover(e) {
|
||||||
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||||
|
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
||||||
|
|
||||||
|
if (isFile || isDriveFile) {
|
||||||
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||||
|
} else {
|
||||||
|
e.dataTransfer.dropEffect = 'none';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onDrop(e): void {
|
onDrop(e): void {
|
||||||
|
@ -101,21 +108,13 @@ export default Vue.extend({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// データ取得
|
//#region ドライブのファイル
|
||||||
const data = e.dataTransfer.getData('text');
|
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
||||||
if (data == null) return;
|
if (driveFile != null && driveFile != '') {
|
||||||
|
const file = JSON.parse(driveFile);
|
||||||
try {
|
this.form.file = file;
|
||||||
// パース
|
|
||||||
const obj = JSON.parse(data);
|
|
||||||
|
|
||||||
// (ドライブの)ファイルだったら
|
|
||||||
if (obj.type == 'file') {
|
|
||||||
this.form.file = obj.file;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// not a json, so noop
|
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchMessages() {
|
fetchMessages() {
|
||||||
|
|
|
@ -115,11 +115,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
onDragstart(e) {
|
onDragstart(e) {
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
e.dataTransfer.effectAllowed = 'move';
|
||||||
e.dataTransfer.setData('text', JSON.stringify({
|
e.dataTransfer.setData('mk_drive_file', JSON.stringify(this.file));
|
||||||
type: 'file',
|
|
||||||
id: this.file.id,
|
|
||||||
file: this.file
|
|
||||||
}));
|
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
|
|
||||||
// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
|
// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
|
||||||
|
|
|
@ -92,19 +92,22 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
onDragover(e) {
|
onDragover(e) {
|
||||||
// 自分自身がドラッグされていない場合
|
// 自分自身がドラッグされている場合
|
||||||
if (!this.isDragging) {
|
if (this.isDragging) {
|
||||||
// ドラッグされてきたものがファイルだったら
|
|
||||||
if (e.dataTransfer.effectAllowed === 'all') {
|
|
||||||
e.dataTransfer.dropEffect = 'copy';
|
|
||||||
} else {
|
|
||||||
e.dataTransfer.dropEffect = 'move';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 自分自身にはドロップさせない
|
// 自分自身にはドロップさせない
|
||||||
e.dataTransfer.dropEffect = 'none';
|
e.dataTransfer.dropEffect = 'none';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||||
|
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
||||||
|
const isDriveFolder = e.dataTransfer.types[0] == 'mk_drive_folder';
|
||||||
|
|
||||||
|
if (isFile || isDriveFile || isDriveFolder) {
|
||||||
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||||
|
} else {
|
||||||
|
e.dataTransfer.dropEffect = 'none';
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onDragenter() {
|
onDragenter() {
|
||||||
|
@ -123,36 +126,35 @@ export default Vue.extend({
|
||||||
Array.from(e.dataTransfer.files).forEach(file => {
|
Array.from(e.dataTransfer.files).forEach(file => {
|
||||||
this.browser.upload(file, this.folder);
|
this.browser.upload(file, this.folder);
|
||||||
});
|
});
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// データ取得
|
//#region ドライブのファイル
|
||||||
const data = e.dataTransfer.getData('text');
|
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
||||||
if (data == null) return false;
|
if (driveFile != null && driveFile != '') {
|
||||||
|
const file = JSON.parse(driveFile);
|
||||||
// パース
|
this.browser.removeFile(file.id);
|
||||||
// TODO: Validate JSON
|
|
||||||
const obj = JSON.parse(data);
|
|
||||||
|
|
||||||
// (ドライブの)ファイルだったら
|
|
||||||
if (obj.type == 'file') {
|
|
||||||
const file = obj.id;
|
|
||||||
this.browser.removeFile(file);
|
|
||||||
(this as any).api('drive/files/update', {
|
(this as any).api('drive/files/update', {
|
||||||
file_id: file,
|
file_id: file.id,
|
||||||
folder_id: this.folder.id
|
folder_id: this.folder.id
|
||||||
});
|
});
|
||||||
// (ドライブの)フォルダーだったら
|
}
|
||||||
} else if (obj.type == 'folder') {
|
//#endregion
|
||||||
const folder = obj.id;
|
|
||||||
|
//#region ドライブのフォルダ
|
||||||
|
const driveFolder = e.dataTransfer.getData('mk_drive_folder');
|
||||||
|
if (driveFolder != null && driveFolder != '') {
|
||||||
|
const folder = JSON.parse(driveFolder);
|
||||||
|
|
||||||
// 移動先が自分自身ならreject
|
// 移動先が自分自身ならreject
|
||||||
if (folder == this.folder.id) return false;
|
if (folder.id == this.folder.id) return;
|
||||||
this.browser.removeFolder(folder);
|
|
||||||
|
this.browser.removeFolder(folder.id);
|
||||||
(this as any).api('drive/folders/update', {
|
(this as any).api('drive/folders/update', {
|
||||||
folder_id: folder,
|
folder_id: folder.id,
|
||||||
parent_id: this.folder.id
|
parent_id: this.folder.id
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// something
|
// noop
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 'detected-circular-definition':
|
case 'detected-circular-definition':
|
||||||
|
@ -169,16 +171,12 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onDragstart(e) {
|
onDragstart(e) {
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
e.dataTransfer.effectAllowed = 'move';
|
||||||
e.dataTransfer.setData('text', JSON.stringify({
|
e.dataTransfer.setData('mk_drive_folder', JSON.stringify(this.folder));
|
||||||
type: 'folder',
|
|
||||||
id: this.folder.id
|
|
||||||
}));
|
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
|
|
||||||
// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
|
// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
|
||||||
|
|
|
@ -41,13 +41,17 @@ export default Vue.extend({
|
||||||
// このフォルダがルートかつカレントディレクトリならドロップ禁止
|
// このフォルダがルートかつカレントディレクトリならドロップ禁止
|
||||||
if (this.folder == null && this.browser.folder == null) {
|
if (this.folder == null && this.browser.folder == null) {
|
||||||
e.dataTransfer.dropEffect = 'none';
|
e.dataTransfer.dropEffect = 'none';
|
||||||
// ドラッグされてきたものがファイルだったら
|
|
||||||
} else if (e.dataTransfer.effectAllowed == 'all') {
|
|
||||||
e.dataTransfer.dropEffect = 'copy';
|
|
||||||
} else {
|
|
||||||
e.dataTransfer.dropEffect = 'move';
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||||
|
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
||||||
|
const isDriveFolder = e.dataTransfer.types[0] == 'mk_drive_folder';
|
||||||
|
|
||||||
|
if (isFile || isDriveFile || isDriveFolder) {
|
||||||
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||||
|
} else {
|
||||||
|
e.dataTransfer.dropEffect = 'none';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onDragenter() {
|
onDragenter() {
|
||||||
if (this.folder || this.browser.folder) this.draghover = true;
|
if (this.folder || this.browser.folder) this.draghover = true;
|
||||||
|
@ -63,38 +67,34 @@ export default Vue.extend({
|
||||||
Array.from(e.dataTransfer.files).forEach(file => {
|
Array.from(e.dataTransfer.files).forEach(file => {
|
||||||
this.browser.upload(file, this.folder);
|
this.browser.upload(file, this.folder);
|
||||||
});
|
});
|
||||||
return false;
|
return;
|
||||||
};
|
}
|
||||||
|
|
||||||
// データ取得
|
//#region ドライブのファイル
|
||||||
const data = e.dataTransfer.getData('text');
|
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
||||||
if (data == null) return false;
|
if (driveFile != null && driveFile != '') {
|
||||||
|
const file = JSON.parse(driveFile);
|
||||||
// パース
|
this.browser.removeFile(file.id);
|
||||||
// TODO: Validate JSON
|
|
||||||
const obj = JSON.parse(data);
|
|
||||||
|
|
||||||
// (ドライブの)ファイルだったら
|
|
||||||
if (obj.type == 'file') {
|
|
||||||
const file = obj.id;
|
|
||||||
this.browser.removeFile(file);
|
|
||||||
(this as any).api('drive/files/update', {
|
(this as any).api('drive/files/update', {
|
||||||
file_id: file,
|
file_id: file.id,
|
||||||
folder_id: this.folder ? this.folder.id : null
|
folder_id: this.folder ? this.folder.id : null
|
||||||
});
|
});
|
||||||
// (ドライブの)フォルダーだったら
|
}
|
||||||
} else if (obj.type == 'folder') {
|
//#endregion
|
||||||
const folder = obj.id;
|
|
||||||
|
//#region ドライブのフォルダ
|
||||||
|
const driveFolder = e.dataTransfer.getData('mk_drive_folder');
|
||||||
|
if (driveFolder != null && driveFolder != '') {
|
||||||
|
const folder = JSON.parse(driveFolder);
|
||||||
// 移動先が自分自身ならreject
|
// 移動先が自分自身ならreject
|
||||||
if (this.folder && folder == this.folder.id) return false;
|
if (this.folder && folder.id == this.folder.id) return;
|
||||||
this.browser.removeFolder(folder);
|
this.browser.removeFolder(folder.id);
|
||||||
(this as any).api('drive/folders/update', {
|
(this as any).api('drive/folders/update', {
|
||||||
folder_id: folder,
|
folder_id: folder.id,
|
||||||
parent_id: this.folder ? this.folder.id : null
|
parent_id: this.folder ? this.folder.id : null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -235,15 +235,21 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
onDragover(e): any {
|
onDragover(e): any {
|
||||||
// ドラッグ元が自分自身の所有するアイテムかどうか
|
// ドラッグ元が自分自身の所有するアイテムだったら
|
||||||
if (!this.isDragSource) {
|
if (this.isDragSource) {
|
||||||
// ドラッグされてきたものがファイルだったら
|
|
||||||
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
|
||||||
this.draghover = true;
|
|
||||||
} else {
|
|
||||||
// 自分自身にはドロップさせない
|
// 自分自身にはドロップさせない
|
||||||
e.dataTransfer.dropEffect = 'none';
|
e.dataTransfer.dropEffect = 'none';
|
||||||
return false;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||||
|
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
||||||
|
const isDriveFolder = e.dataTransfer.types[0] == 'mk_drive_folder';
|
||||||
|
|
||||||
|
if (isFile || isDriveFile || isDriveFolder) {
|
||||||
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||||
|
} else {
|
||||||
|
e.dataTransfer.dropEffect = 'none';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -263,38 +269,36 @@ export default Vue.extend({
|
||||||
Array.from(e.dataTransfer.files).forEach(file => {
|
Array.from(e.dataTransfer.files).forEach(file => {
|
||||||
this.upload(file, this.folder);
|
this.upload(file, this.folder);
|
||||||
});
|
});
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// データ取得
|
//#region ドライブのファイル
|
||||||
const data = e.dataTransfer.getData('text');
|
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
||||||
if (data == null) return false;
|
if (driveFile != null && driveFile != '') {
|
||||||
|
const file = JSON.parse(driveFile);
|
||||||
// パース
|
if (this.files.some(f => f.id == file.id)) return;
|
||||||
// TODO: JSONじゃなかったら中断
|
this.removeFile(file.id);
|
||||||
const obj = JSON.parse(data);
|
|
||||||
|
|
||||||
// (ドライブの)ファイルだったら
|
|
||||||
if (obj.type == 'file') {
|
|
||||||
const file = obj.id;
|
|
||||||
if (this.files.some(f => f.id == file)) return false;
|
|
||||||
this.removeFile(file);
|
|
||||||
(this as any).api('drive/files/update', {
|
(this as any).api('drive/files/update', {
|
||||||
file_id: file,
|
file_id: file.id,
|
||||||
folder_id: this.folder ? this.folder.id : null
|
folder_id: this.folder ? this.folder.id : null
|
||||||
});
|
});
|
||||||
// (ドライブの)フォルダーだったら
|
}
|
||||||
} else if (obj.type == 'folder') {
|
//#endregion
|
||||||
const folder = obj.id;
|
|
||||||
|
//#region ドライブのフォルダ
|
||||||
|
const driveFolder = e.dataTransfer.getData('mk_drive_folder');
|
||||||
|
if (driveFolder != null && driveFolder != '') {
|
||||||
|
const folder = JSON.parse(driveFolder);
|
||||||
|
|
||||||
// 移動先が自分自身ならreject
|
// 移動先が自分自身ならreject
|
||||||
if (this.folder && folder == this.folder.id) return false;
|
if (this.folder && folder.id == this.folder.id) return false;
|
||||||
if (this.folders.some(f => f.id == folder)) return false;
|
if (this.folders.some(f => f.id == folder.id)) return false;
|
||||||
this.removeFolder(folder);
|
this.removeFolder(folder.id);
|
||||||
(this as any).api('drive/folders/update', {
|
(this as any).api('drive/folders/update', {
|
||||||
folder_id: folder,
|
folder_id: folder.id,
|
||||||
parent_id: this.folder ? this.folder.id : null
|
parent_id: this.folder ? this.folder.id : null
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// something
|
// noop
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 'detected-circular-definition':
|
case 'detected-circular-definition':
|
||||||
|
@ -311,8 +315,7 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
selectLocalFile() {
|
selectLocalFile() {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mk-post-form"
|
<div class="mk-post-form"
|
||||||
@dragover.prevent.stop="onDragover"
|
@dragover.stop="onDragover"
|
||||||
@dragenter="onDragenter"
|
@dragenter="onDragenter"
|
||||||
@dragleave="onDragleave"
|
@dragleave="onDragleave"
|
||||||
@drop.prevent.stop="onDrop"
|
@drop.stop="onDrop"
|
||||||
>
|
>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<textarea :class="{ with: (files.length != 0 || poll) }"
|
<textarea :class="{ with: (files.length != 0 || poll) }"
|
||||||
|
@ -159,8 +159,13 @@ export default Vue.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onDragover(e) {
|
onDragover(e) {
|
||||||
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||||
|
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
||||||
|
if (isFile || isDriveFile) {
|
||||||
|
e.preventDefault();
|
||||||
this.draghover = true;
|
this.draghover = true;
|
||||||
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onDragenter(e) {
|
onDragenter(e) {
|
||||||
this.draghover = true;
|
this.draghover = true;
|
||||||
|
@ -173,26 +178,20 @@ export default Vue.extend({
|
||||||
|
|
||||||
// ファイルだったら
|
// ファイルだったら
|
||||||
if (e.dataTransfer.files.length > 0) {
|
if (e.dataTransfer.files.length > 0) {
|
||||||
|
e.preventDefault();
|
||||||
Array.from(e.dataTransfer.files).forEach(this.upload);
|
Array.from(e.dataTransfer.files).forEach(this.upload);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// データ取得
|
//#region ドライブのファイル
|
||||||
const data = e.dataTransfer.getData('text');
|
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
||||||
if (data == null) return;
|
if (driveFile != null && driveFile != '') {
|
||||||
|
const file = JSON.parse(driveFile);
|
||||||
try {
|
this.files.push(file);
|
||||||
// パース
|
|
||||||
const obj = JSON.parse(data);
|
|
||||||
|
|
||||||
// (ドライブの)ファイルだったら
|
|
||||||
if (obj.type == 'file') {
|
|
||||||
this.files.push(obj.file);
|
|
||||||
this.$emit('change-attached-media', this.files);
|
this.$emit('change-attached-media', this.files);
|
||||||
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
//#endregion
|
||||||
// not a json, so noop
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
post() {
|
post() {
|
||||||
this.posting = true;
|
this.posting = true;
|
||||||
|
|
Loading…
Reference in a new issue