Skip to content

Commit

Permalink
Fix drag and drop problem. Fix issue xdan#19
Browse files Browse the repository at this point in the history
  • Loading branch information
xdan committed Feb 27, 2018
1 parent 3811860 commit ee5d630
Show file tree
Hide file tree
Showing 15 changed files with 347 additions and 153 deletions.
1 change: 1 addition & 0 deletions custom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ declare module "*.svg" {
}

type Bound = {top: number, left: number, width: number, height: number};
type Point = {x: number, y: number};
type SelectionRange = {
startContainer: Node|null,
startOffset: number|null,
Expand Down
2 changes: 1 addition & 1 deletion src/Jodit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ export class Jodit extends Component {

// proxy events
this.events
.on(this.editor, 'keydown keyup keypress mousedown mouseup mousepress click copy paste resize touchstart touchend focus blur', (event: Event): false | void => {
.on(this.editor, 'keydown keyup keypress mousedown mouseup mousepress click copy dragstart drop dragover paste resize touchstart touchend focus blur', (event: Event): false | void => {
if (this.options.readonly) {
return;
}
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const MODE_SPLIT = 3;
/**
* @property {string} TEXT_PLAIN='text/plain' For IE11 it will be 'text'. Need for dataTransfer.setData
*/
export const URL_LIST = navigator.userAgent.indexOf("MSIE") != -1 || /rv:11.0/i.test(navigator.userAgent) ? 'url' : 'text/uri-list';
export const TEXT_PLAIN = navigator.userAgent.indexOf("MSIE") != -1 || /rv:11.0/i.test(navigator.userAgent) ? 'text' : 'text/plain';
export const TEXT_HTML = navigator.userAgent.indexOf("MSIE") != -1 || /rv:11.0/i.test(navigator.userAgent) ? 'text' : 'text/html';

Expand Down
6 changes: 3 additions & 3 deletions src/modules/Dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -533,11 +533,11 @@ export class Dom {
*
* @param root
* @param child
* @param boolean [onliConatins]
* @param boolean [onlyContains]
* @return {boolean}
*/
static isOrContains = (root: Node, child: Node, onliConatins: boolean = false): boolean => {
return child && root && ((root === child && !onliConatins) || Dom.contains(root, child));
static isOrContains = (root: Node, child: Node, onlyContains: boolean = false): boolean => {
return child && root && ((root === child && !onlyContains) || Dom.contains(root, child));
};

/*static apply = (options, addPropertyCallback, editor: Jodit) => {
Expand Down
102 changes: 59 additions & 43 deletions src/modules/FileBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,8 +464,10 @@ Config.prototype.filebrowser = <FileBrowserOptions>{
${(this.options.showFileChangeTime && item.changed) ? `<span class="${ITEM_CLASS}-info-filechanged">${item.changed}</span>` : ''}
</div>`;

return `<a draggable="true" class="${ITEM_CLASS}" href="${urlNormalize(source.baseurl + source.path + name)}" data-source="${source_name}" data-path="${pathNormalize(source.path ? source.path + '/' : '/')}" data-name="${name}" title="${name}" data-url="${urlNormalize(source.baseurl + source.path + name)}">
<img src="${urlNormalize(source.baseurl + source.path + thumb)}?_tmst=${timestamp}" alt="${name}"/>
let imageURL: string = urlNormalize(source.baseurl + source.path + name);

return `<a draggable="true" class="${ITEM_CLASS}" href="${imageURL}" data-source="${source_name}" data-path="${pathNormalize(source.path ? source.path + '/' : '/')}" data-name="${name}" title="${name}" data-url="${imageURL}">
<img data-src="${imageURL}" src="${urlNormalize(source.baseurl + source.path + thumb)}?_tmst=${timestamp}" alt="${name}"/>
${(this.options.showFileName || (this.options.showFileSize && item.size) || (this.options.showFileChangeTime && item.changed)) ? info : ''}
</a>`;
},
Expand Down Expand Up @@ -740,31 +742,44 @@ export class FileBrowser extends Component implements IViewBased {
const contextmenu: ContextMenu = new ContextMenu(this.jodit || this);

self.events
.on(self.files, 'mousedown', function (this: HTMLElement, e: DragEvent) {
self.client.x = e.clientX;
self.client.y = e.clientY;

self.start = offset(this, self.jodit);

self.draggable = <HTMLElement>this.cloneNode(true);

css(<HTMLElement>self.draggable, {
'z-index': 100000000000000,
position: 'fixed',
display: 'none',
left: self.start.left,
top: self.start.top,
width: this.offsetWidth,
height: this.offsetHeight
});

doc.body.appendChild(self.draggable)
}, 'a>img')
.on(self.files, 'dragstart', function (this: HTMLElement, e: DragEvent) {
self.dragger = this;
e.dataTransfer.setData(consts.TEXT_PLAIN, this.getAttribute('href') || '');
e.stopPropagation();
}, 'a')
// .on(self.files, 'mousedown', function (this: HTMLElement, e: DragEvent) {
// self.client.x = e.clientX;
// self.client.y = e.clientY;
//
// self.start = offset(this, self.jodit);
//
// self.draggable = <HTMLElement>this.cloneNode(true);
//
// css(<HTMLElement>self.draggable, {
// 'z-index': 100000000000000,
// position: 'fixed',
// display: 'none',
// left: self.start.left,
// top: self.start.top,
// width: this.offsetWidth,
// height: this.offsetHeight
// });
//
// doc.body.appendChild(self.draggable)
// }, 'a>img')
// .on(self.files, 'dragstart', function (this: HTMLElement, e: DragEvent) {
// self.dragger = this;
// let img = new Image();
// img.src = this.getAttribute('href') || '';
// // e.dataTransfer.clearData();
// e.dataTransfer.dropEffect = "copy";
//
// if (e.dataTransfer.setDragImage) {
// e.dataTransfer.setDragImage(img, 10, 10);
// } else {
// e.dataTransfer.setData(consts.TEXT_PLAIN, this.getAttribute('href') || '');
// }
//
// // e.dataTransfer.setDragImage(<HTMLElement>this.querySelector('img'), 1, 1);//add(consts.TEXT_PLAIN, this.getAttribute('href') || '');
// // e.dataTransfer.setData(consts.TEXT_PLAIN, this.getAttribute('href') || '');
// e.stopPropagation();
// // e.preventDefault();
// }, 'a')
.on(self.files, 'contextmenu', function (this: HTMLElement, e: DragEvent): boolean | void {
if (self.options.contextMenu) {
let item: HTMLElement = this;
Expand Down Expand Up @@ -886,26 +901,27 @@ export class FileBrowser extends Component implements IViewBased {
e.stopPropagation();
return false;
}, 'a')
.on(self.ownerDocument, 'dragover', function (e: MouseEvent) {
if (self.isOpened() && self.draggable && e.clientX !== undefined) {
css(self.draggable, {
left: e.clientX + 20,
top: e.clientY + 20,
display: 'block'
});
}
})
// .on(self.ownerDocument, 'dragover', function (e: MouseEvent) {
// if (self.isOpened() && self.draggable && e.clientX !== undefined) {
// css(self.draggable, {
// left: e.clientX + 20,
// top: e.clientY + 20,
// display: 'block'
// });
// }
// })
.on(self.dialog.dialogbox, 'drop', (e: DragEvent) => e.preventDefault())
.on(self.ownerWindow, 'keydown', (e: KeyboardEvent) => {
if (self.isOpened() && e.which === consts.KEY_DELETE) {
self.events.fire(self.buttons.remove, 'click');
}
})
.on(self.ownerWindow, 'mouseup dragend',() => {
if (self.draggable) {
self.draggable.parentNode && self.draggable.parentNode.removeChild(self.draggable);
self.draggable = false;
}
});
// .on(self.ownerWindow, 'mouseup dragend',() => {
// if (self.draggable) {
// self.draggable.parentNode && self.draggable.parentNode.removeChild(self.draggable);
// self.draggable = false;
// }
// });

this.dialog.setSize(this.options.width, this.options.height);

Expand Down Expand Up @@ -1468,7 +1484,7 @@ export class FileBrowser extends Component implements IViewBased {
});
};

private draggable: HTMLElement|false = false;
private draggable: HTMLElement | false = false;
private start = {top: 0, left: 0};
private client = {x: 0, y: 0};
}
19 changes: 19 additions & 0 deletions src/modules/Helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1116,4 +1116,23 @@ export const getXPathByElement = (element: HTMLElement, root: HTMLElement): stri
const sames: Node[] = [].filter.call(element.parentNode.childNodes, (x: Node) => x.nodeName === element.nodeName);

return getXPathByElement(<HTMLElement>element.parentNode, root) + '/' + element.nodeName.toLowerCase() + (sames.length > 1 ? '['+([].indexOf.call(sames, element)+1)+']' : '')
};

const dataBindKey = 'JoditDataBindkey';
export const dataBind = (elm: any, key: string, value?: any) => {
let store = elm[dataBindKey];
if (!store) {
store = {};
Object.defineProperty(elm, dataBindKey, {
enumerable: false,
configurable: true,
value: store
});
}

if (value === undefined) {
return store[key];
}

store[key] = value;
};
1 change: 1 addition & 0 deletions src/modules/Plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export abstract class Plugin extends Component{
}

abstract afterInit(): void;

beforeDestruct() {};
}
16 changes: 10 additions & 6 deletions src/modules/Selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,29 @@ export class Select extends Component{
this.removeMarkers();

try {
let rng: Range = doc.createRange();
let rng: Range | null = null;

if ((<any>doc).caretPositionFromPoint) {
caret = (<any>doc).caretPositionFromPoint(x, y);
rng = doc.createRange();
rng.setStart(caret.offsetNode, caret.offset);
} else if (this.jodit.editorDocument.caretRangeFromPoint) {
caret = this.jodit.editorDocument.caretRangeFromPoint(x, y);
rng = this.jodit.editorDocument.createRange();
} else if (doc.caretRangeFromPoint) {
caret = doc.caretRangeFromPoint(x, y);
rng = doc.createRange();
rng.setStart(caret.startContainer, caret.startOffset);
}

if (rng && typeof this.jodit.editorWindow.getSelection != "undefined") {
rng.collapse(true);
let sel: Selection = this.jodit.editorWindow.getSelection();
const sel: Selection = this.jodit.editorWindow.getSelection();
sel.removeAllRanges();
sel.addRange(rng);
} else if (typeof (<any>doc).body.createTextRange !== "undefined") {
let range: any = (<any>doc).body.createTextRange();
const range: any = (<any>doc).body.createTextRange();
range.moveToPoint(x, y);
const endRange: any = range.duplicate();
endRange.moveToPoint(x, y);
range.setEndPoint("EndToEnd", endRange);
range.select();
}

Expand Down
43 changes: 17 additions & 26 deletions src/modules/Uploader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {Component, IViewBased} from './Component';
import {Ajax} from './Ajax';
import {Config} from '../Config'
import {browser, extend, isPlainObject} from "./Helpers";
import {TEXT_PLAIN} from "../constants";
import {TEXT_HTML, TEXT_PLAIN, URL_LIST} from "../constants";
import {Dom} from "./Dom";
import {Select} from "./Selection";

Expand Down Expand Up @@ -460,39 +460,30 @@ export class Uploader {
.on('processPaste', onPaste)
}

const hasFiles = (event: DragEvent) : boolean => event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length !== 0;

self.jodit.events
.on(form, "dragover", (event: DragEvent) => {
form.classList.add('draghover');
if (hasFiles(event)) {
form.classList.contains('jodit_draghover') ||
form.classList.add('jodit_draghover');
}

event.preventDefault();
})
.on(form, "dragleave dragend", (event: DragEvent) => {
form.classList.remove('draghover');
event.preventDefault();
.on(form, "dragend", (event: DragEvent) => {
if (hasFiles(event)) {
form.classList.contains('jodit_draghover') && form.classList.remove('jodit_draghover');
event.preventDefault();
}
})
.on(form, "drop", (event: DragEvent): false | void => {
form.classList.remove('draghover');
if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length) {
form.classList.remove('jodit_draghover');

if (hasFiles(event)) {
event.preventDefault();
event.stopImmediatePropagation();
this.sendFiles(event.dataTransfer.files, handlerSuccess, handlerError);
} else if (event.dataTransfer && event.dataTransfer.getData(TEXT_PLAIN) && event.dataTransfer.getData(TEXT_PLAIN) !== '-' && form === self.jodit.editor) {
event.preventDefault();
event.stopPropagation();
if (!this.selection.insertCursorAtPoint(event.clientX, event.clientY)) {
return false;
}
if (handlerSuccess || this.options.defaultHandlerSuccess) {
let data: {
baseurl: string,
files: string[]
} = {
baseurl: '',
files: []
};
data.files = [event.dataTransfer.getData(TEXT_PLAIN)];

(handlerSuccess || this.options.defaultHandlerSuccess).call(this, data);
}
event.preventDefault();
}
});

Expand Down
Loading

0 comments on commit ee5d630

Please sign in to comment.