Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(IText): Draggable text #7802

Merged
merged 103 commits into from
Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
4a00d88
feat(IText): native like text dragging
ShaMan123 Mar 11, 2022
d6d1eae
fire event on object
ShaMan123 Mar 11, 2022
672f945
Update itext_click_behavior.mixin.js
ShaMan123 Mar 11, 2022
0298b3b
lint
ShaMan123 Mar 11, 2022
c7a39a0
dragend
ShaMan123 Mar 12, 2022
f5957c8
Update itext_click_behavior.mixin.js
ShaMan123 Mar 12, 2022
d4bdf7f
Update itext_click_behavior.mixin.js
ShaMan123 Mar 12, 2022
a77f365
dragover + drop
ShaMan123 Mar 12, 2022
51c06ae
Update itext_behavior.mixin.js
ShaMan123 Mar 12, 2022
a04e57d
Update itext_behavior.mixin.js
ShaMan123 Mar 12, 2022
04ee04f
Update itext_click_behavior.mixin.js
ShaMan123 Mar 12, 2022
afedfc2
fix(): drag end
ShaMan123 Mar 12, 2022
fc00090
Update itext_behavior.mixin.js
ShaMan123 Mar 12, 2022
7dfa629
support `editable`/`canDrop`
ShaMan123 Mar 12, 2022
934dd3c
Update itext_behavior.mixin.js
ShaMan123 Mar 12, 2022
f70651c
lint
ShaMan123 Mar 12, 2022
3d32720
Update itext_behavior.mixin.js
ShaMan123 Mar 12, 2022
34bc7b5
fix bug
ShaMan123 Mar 12, 2022
7ce1e7d
point
ShaMan123 Mar 13, 2022
8d500b3
drag image
ShaMan123 Mar 13, 2022
de9ca36
fix: drag over controls
ShaMan123 Mar 13, 2022
aa8c371
Update itext_behavior.mixin.js
ShaMan123 Mar 13, 2022
0efa15a
JSDOC
ShaMan123 Mar 13, 2022
4f457b9
Update canvas_events.js
ShaMan123 Mar 13, 2022
4d516ea
Update itext_behavior.mixin.js
ShaMan123 Mar 13, 2022
76d2a4d
Update itext_behavior.mixin.js
ShaMan123 Mar 14, 2022
cbe456c
cleanup
ShaMan123 Mar 14, 2022
6047c29
Update itext.class.js
ShaMan123 Mar 14, 2022
3df67f2
Update itext.class.js
ShaMan123 Mar 14, 2022
784a27a
setDragImage
ShaMan123 Mar 14, 2022
17b3f9a
revert `getRelativeCursorPosition`
ShaMan123 Mar 14, 2022
1ae3043
Update itext_behavior.mixin.js
ShaMan123 Mar 14, 2022
8fdf77b
retina scaling
ShaMan123 Mar 14, 2022
d112f3b
fix(): drag image offset
ShaMan123 Mar 14, 2022
57e81a1
Update itext_behavior.mixin.js
ShaMan123 Mar 14, 2022
63bbdfe
better drag image
ShaMan123 Mar 14, 2022
1b640f5
Update itext_behavior.mixin.js
ShaMan123 Mar 14, 2022
a2d2225
support styles
ShaMan123 Mar 14, 2022
48e2dde
dragstart + trailing spcae
ShaMan123 Mar 14, 2022
eef6895
drop + trailing space
ShaMan123 Mar 14, 2022
34b5686
fix: edit after drop + selection
ShaMan123 Mar 14, 2022
f6f701a
Update itext_behavior.mixin.js
ShaMan123 Mar 14, 2022
10a43d9
Update itext_behavior.mixin.js
ShaMan123 Mar 14, 2022
4642784
Update itext_behavior.mixin.js
ShaMan123 Mar 14, 2022
8e69763
refactor clipboard events
ShaMan123 Mar 14, 2022
4d441f3
finalize clipboard data
ShaMan123 Mar 14, 2022
e78310a
JSDOC
ShaMan123 Mar 14, 2022
f6d1311
lint
ShaMan123 Mar 14, 2022
04f379a
rtl support prep
ShaMan123 Mar 14, 2022
f9ed862
Update itext_key_behaviour.js
ShaMan123 Mar 14, 2022
c257c91
Update itext_key_behaviour.js
ShaMan123 Mar 14, 2022
72b9a77
Update itext_key_behavior.mixin.js
ShaMan123 Mar 14, 2022
df3f7f2
Update itext_behavior.mixin.js
ShaMan123 Mar 21, 2022
efdd61e
typo
ShaMan123 Mar 22, 2022
97cebb1
remove `disableStyleCopyPaste`
ShaMan123 Mar 22, 2022
ab637ac
Merge branch 'master' into draggable-text
ShaMan123 Mar 29, 2022
fe7cc4d
Merge branch 'master' into draggable-text
ShaMan123 Apr 2, 2022
8b06dfe
fix(): can't drop over selection
ShaMan123 Apr 2, 2022
1b12168
render drag selection
ShaMan123 Apr 2, 2022
6b8a1d9
renderDragStartSelection
ShaMan123 Apr 2, 2022
49aa851
better drag selection start rendering
ShaMan123 Apr 2, 2022
cfa7445
Update itext_behavior.mixin.js
ShaMan123 Apr 2, 2022
6033478
Update itext.class.js
ShaMan123 Apr 2, 2022
33d1cd6
Update itext.class.js
ShaMan123 Apr 2, 2022
f7ed62c
fix drag start selection
ShaMan123 Apr 2, 2022
46206b1
remove `trailingSpace` logic
ShaMan123 Apr 2, 2022
cdf9abd
fix(): clear context
ShaMan123 Apr 2, 2022
a9ca01e
Update itext_behavior.mixin.js
ShaMan123 Apr 2, 2022
de44140
lint
ShaMan123 Apr 2, 2022
c8b413b
fix: dragleave on canvas
ShaMan123 Apr 2, 2022
2069128
Update canvas_events.js
ShaMan123 Apr 2, 2022
c8c10f0
fix dragenter
ShaMan123 Apr 2, 2022
513199f
Update canvas_events.js
ShaMan123 Apr 2, 2022
d610383
Update canvas_events.js
ShaMan123 Apr 2, 2022
9ebdc62
fire always
ShaMan123 Apr 2, 2022
0d89e2b
Update canvas_events.mixin.js
ShaMan123 Apr 2, 2022
9734207
dragend
ShaMan123 Apr 2, 2022
c181512
Update itext_key_behavior.mixin.js
ShaMan123 Apr 2, 2022
29456b1
Update itext_behavior.mixin.js
ShaMan123 Apr 2, 2022
4058520
Update itext_behavior.mixin.js
ShaMan123 Apr 2, 2022
61c96fa
Update itext_behavior.mixin.js
ShaMan123 Apr 2, 2022
ea9c099
fix(): dragsource dragend edit mode state
ShaMan123 Apr 2, 2022
829bc67
Update itext_behavior.mixin.js
ShaMan123 Apr 2, 2022
43afb2e
Update canvas_events.mixin.js
ShaMan123 Apr 2, 2022
fd8515c
lint
ShaMan123 Apr 2, 2022
ecbf266
Update itext_behavior.mixin.js
ShaMan123 Apr 2, 2022
bd2b6c3
Update canvas_events.mixin.js
ShaMan123 Apr 2, 2022
a875dfe
Revert "Update itext_behavior.mixin.js"
ShaMan123 Apr 2, 2022
bc4e4c1
Update itext_behavior.mixin.js
ShaMan123 Apr 2, 2022
186d26d
fix(): always fire events
ShaMan123 Apr 3, 2022
d4fa70c
dragSource attr on drop event
ShaMan123 Apr 3, 2022
23f450f
fix(): firing `drag` event on drag source
ShaMan123 Apr 3, 2022
c60716d
lint
ShaMan123 Apr 3, 2022
0ebb4bb
fire dragstart on canvas
ShaMan123 Apr 3, 2022
61a48f7
Merge branch 'master' into draggable-text
ShaMan123 Apr 3, 2022
a6b5aa1
revert clipboard event changes
ShaMan123 Apr 25, 2022
51e15fe
revert: remove `disableStyleCopyPaste`
ShaMan123 Apr 25, 2022
d07d6d3
Merge branch 'master' into draggable-text
ShaMan123 May 1, 2022
be4cf22
Merge branch 'master' into draggable-text
ShaMan123 Jun 10, 2022
d6f9c8f
Merge branch 'master' into draggable-text
ShaMan123 Jul 5, 2022
b38b34c
add additional tweaks
ShaMan123 Jul 9, 2022
2db76ec
lint
ShaMan123 Jul 10, 2022
f00e547
Changes for text dragging (#8065)
asturur Jul 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions src/canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -943,19 +943,16 @@

if (boundsWidth === 0 || boundsHeight === 0) {
// If bounds are not available (i.e. not visible), do not apply scale.
cssScale = { width: 1, height: 1 };
cssScale = { x: 1, y: 1 };
}
else {
cssScale = {
width: upperCanvasEl.width / boundsWidth,
height: upperCanvasEl.height / boundsHeight
x: upperCanvasEl.width / boundsWidth,
y: upperCanvasEl.height / boundsHeight
};
}

return {
x: pointer.x * cssScale.width,
y: pointer.y * cssScale.height
};
return pointer.multiply(cssScale);
},

/**
Expand All @@ -980,6 +977,7 @@

this._copyCanvasStyle(lowerCanvasEl, upperCanvasEl);
this._applyCanvasStyle(upperCanvasEl);
upperCanvasEl.setAttribute('draggable', 'true');
this.contextTop = upperCanvasEl.getContext('2d');
},

Expand Down
39 changes: 37 additions & 2 deletions src/mixins/canvas_events.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
functor(canvasElement, 'wheel', this._onMouseWheel);
functor(canvasElement, 'contextmenu', this._onContextMenu);
functor(canvasElement, 'dblclick', this._onDoubleClick);
functor(canvasElement, 'dragstart', this._onDragStart);
functor(canvasElement, 'dragend', this._onDragEnd);
functor(canvasElement, 'dragover', this._onDragOver);
functor(canvasElement, 'dragenter', this._onDragEnter);
functor(canvasElement, 'dragleave', this._onDragLeave);
Expand Down Expand Up @@ -103,6 +105,8 @@
this._onMouseEnter = this._onMouseEnter.bind(this);
this._onContextMenu = this._onContextMenu.bind(this);
this._onDoubleClick = this._onDoubleClick.bind(this);
this._onDragStart = this._onDragStart.bind(this);
this._onDragEnd = this._onDragEnd.bind(this);
this._onDragOver = this._onDragOver.bind(this);
this._onDragEnter = this._simpleEventHandler.bind(this, 'dragenter');
this._onDragLeave = this._simpleEventHandler.bind(this, 'dragleave');
Expand Down Expand Up @@ -207,14 +211,43 @@
this.__onLongPress && this.__onLongPress(e, self);
},

/**
* supports native like text dragging
* @private
* @param {DragEvent} e
*/
_onDragStart: function (e) {
var activeObject = this.getActiveObject();
if (activeObject && typeof activeObject.onDragStart === 'function' && activeObject.onDragStart(e)) {
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
this._dragSource = activeObject;
return;
}
e.preventDefault();
e.stopPropagation();
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would prefer to call this _onDragStartTextInternal ( or similar ) and short circuit if the active object type does not inherit from text rather than checking if the activeObject has onDragStart function.

If more drag/drop functionality get added in the future, each functionality can have its own handler and they can be turned off easily by not registering the event handler or de-registering it.

Copy link
Contributor Author

@ShaMan123 ShaMan123 Apr 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree because this way any object can utilize this logic out of the box.
The place to disable the event is from onDragStart - this is from the spec.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to open the doors to drag things that we didn't plan to support.
We are not adding text drag support, with a skeleton of infrastructure to do maybe more dragging, but we don't really know.
It is easier to add later than rollback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you agree with the naming onDragStart?
It is meant for override same as onSelect


/**
* supports native like text dragging
* https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#finishing_a_drag
* @private
* @param {DragEvent} e
*/
_onDragEnd: function (e) {
this._dragSource && typeof this._dragSource.onDragEnd === 'function' && this._dragSource.onDragEnd(e);
delete this._dragSource;
// we need to call mouse up synthetically because the browser won't
this._onMouseUp(e);
},

/**
* prevent default to allow drop event to be fired
* https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#specifying_drop_targets
* @private
* @param {Event} [e] Event object fired on Event.js shake
*/
_onDragOver: function(e) {
e.preventDefault();
var target = this._simpleEventHandler('dragover', e);
target && (!target.canDrop || target.canDrop(e)) && e.preventDefault();
this._fireEnterLeaveEvents(target, e);
},

Expand Down Expand Up @@ -374,7 +407,9 @@
* @param {Event} e Event object fired on mousemove
*/
_onMouseMove: function (e) {
!this.allowTouchScrolling && e.preventDefault && e.preventDefault();
var activeObject = this.getActiveObject();
!this.allowTouchScrolling && (!activeObject || !activeObject.__isDragging)
&& e.preventDefault && e.preventDefault();
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
this.__onMouseMove(e);
},

Expand Down
252 changes: 252 additions & 0 deletions src/mixins/itext_behavior.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
this.initCursorSelectionHandlers();
this.initDoubleClickSimulation();
this.mouseMoveHandler = this.mouseMoveHandler.bind(this);
this.dragOverHandler = this.dragOverHandler.bind(this);
this.dragLeaveHandler = this.dragLeaveHandler.bind(this);
this.dropHandler = this.dropHandler.bind(this);
this.on('dragover', this.dragOverHandler);
this.on('dragleave', this.dragLeaveHandler);
this.on('drop', this.dropHandler);
},

onDeselect: function() {
Expand Down Expand Up @@ -412,6 +418,252 @@
}
},

/**
* Override to customize the drag image
* https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage
* @param {DragEvent} e
* @param {object} data
* @param {number} data.selectionStart
* @param {number} data.selectionEnd
* @param {boolean} data.trailingSpace
* @param {string} data.text
* @param {string} data.value selected text
*/
setDragImage: function (e, data) {
var t = this.calcTransformMatrix();
var flipFactor = new fabric.Point(this.flipX ? -1 : 1, this.flipY ? -1 : 1);
var boundaries = this._getCursorBoundaries(data.selectionStart);
var selectionPosition = new fabric.Point(
boundaries.left + boundaries.leftOffset,
boundaries.top + boundaries.topOffset
).multiply(flipFactor);
var pos = fabric.util.transformPoint(selectionPosition, t);
var pointer = this.canvas.getPointer(e);
var diff = pointer.subtract(pos);
var enableRetinaScaling = this.canvas._isRetinaScaling();
var retinaScaling = this.canvas.getRetinaScaling();
var bbox = this.getBoundingRect(true);
var correction = pos.subtract(new fabric.Point(bbox.left, bbox.top));
var offset = correction.add(diff).scalarMultiply(retinaScaling);
// prepare instance for drag image snapshot by making all non selected text invisible
var bgc = this.backgroundColor;
var styles = fabric.util.object.clone(this.styles, true);
delete this.backgroundColor;
var styleOverride = {
fill: 'transparent',
textBackgroundColor: 'transparent'
};
this.setSelectionStyles(styleOverride, 0, data.selectionStart);
this.setSelectionStyles(styleOverride, data.selectionEnd, data.text.length);
var dragImage = this.toCanvasElement({ enableRetinaScaling: enableRetinaScaling });
this.backgroundColor = bgc;
this.styles = styles;
// handle retina scaling
if (enableRetinaScaling && retinaScaling > 1) {
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
var c = fabric.util.createCanvasElement();
c.width = dragImage.width / retinaScaling;
c.height = dragImage.height / retinaScaling;
var ctx = c.getContext('2d');
ctx.scale(1 / retinaScaling, 1 / retinaScaling);
ctx.drawImage(dragImage, 0, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't forget to account for viewport transform

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, would it not be better to keep the dragImage in the original resolution (with retinascaling) and just resize the drag image's dom element so that it stays in high res?

Copy link
Contributor Author

@ShaMan123 ShaMan123 Mar 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please elaborate
resizing by setting width height and applying scale?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested on a high dpi display. The drag image is at a lower dpi than the canvas.

Copy link
Contributor Author

@ShaMan123 ShaMan123 Mar 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have seen that as well.
Any suggestions? Code?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just spent some time looking into this... your code looks correct, I'm really not sure what's causing the dragimage to have a lower res 😐

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not retina scaled because there is probably no css for the drawImage.
indeed here https://github.com/fabricjs/fabric.js/pull/7802/files#diff-af5c45c9018fd92f35ba43f5e25303b5fe3b627d0f81d2d78b328746fe015b4eR468-R473 we are dividing the natural size of the image by the retina factor, making it smaller.
Not sure if the dragged image can targeted by a selector, or can be wrapped in a div and added a class that would retina-scale it.
Is not that much important we can try later

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If i remember correctly, when handling drag/drop with react.js i remember the dragged element can be anything. I believe you can remove the division by retina scaling and add a div around the canvas that will divide the size by 2 with css and so get the hiDpi effect.

dragImage = c;
}
this.__dragImageDisposer && this.__dragImageDisposer();
this.__dragImageDisposer = function () {
dragImage.remove();
};
// position drag image offsecreen
fabric.util.setStyle(dragImage, {
position: 'absolute',
left: -dragImage.width + 'px'
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
});
fabric.document.body.appendChild(dragImage);
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
e.dataTransfer.setDragImage(dragImage, offset.x, offset.y);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@melchiar try manipulating the offset value
Perhaps firefox accounts for retina scaling?

},

/**
* support native like text dragging
* @private
* @param {DragEvent} e
* @returns {boolean} should handle event
*/
onDragStart: function (e) {
this.__dragStartFired = true;
if (this.__isDragging) {
var trailing = this._text[this.selectionEnd];
var trailingSpace = this._reNewline.test(trailing) ?
this.findLineBoundaryLeft(this.selectionStart) === this.selectionStart
&& this.findLineBoundaryRight(this.selectionEnd) === this.selectionEnd :
this.findWordBoundaryRight(this.selectionEnd - 1) === this.selectionEnd;
var selection = this.__dragStartSelection = {
selectionStart: this.selectionStart,
selectionEnd: this.selectionEnd + trailingSpace,
trailingSpace: trailingSpace
};
var value = this._text.slice(selection.selectionStart, selection.selectionEnd).join('');
var data = Object.assign({ text: this.text, value: value }, selection);
e.dataTransfer.setData('text/plain', value);
e.dataTransfer.setData('application/fabric', JSON.stringify({
value: value,
styles: this.getSelectionStyles(selection.selectionStart, selection.selectionEnd, true),
trailingSpace: trailingSpace
}));
e.dataTransfer.effectAllowed = 'copyMove';
e.dataTransfer.dropEffect = 'move';
this.setDragImage(e, data);
this.fire('dragstart', { e: e, data: data });
}
return this.__isDragging;
},

/**
* Override to customize drag and drop behavior
* @public
* @param {DragEvent} e
* @returns {boolean}
*/
canDrop: function (e) { // eslint-disable-line no-unused-vars
return this.editable && !this.__corner;
},

/**
* support native like text dragging
* @private
*/
dragOverHandler: function (options) {
if (!this.__isDraggingOver && this.canDrop(options.e)) {
this.__isDraggingOver = true;
this.enterEditing(options.e);
}
if (this.__isDraggingOver) {
this.setCursorByClick(options.e);
this._updateTextarea();
this.restartCursorIfNeeded();
this.renderCursorOrSelection();
}
},

/**
* support native like text dragging
* @private
*/
dragLeaveHandler: function () {
if (this.__isDraggingOver) {
this.__isDraggingOver = false;
this.exitEditing();
}
},

/**
* support native like text dragging
* fired only on the drag source
* https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#finishing_a_drag
* @private
* @param {DragEvent} e
* @returns {boolean} should handle event
*/
onDragEnd: function (e) {
if (this.__isDragging && this.__dragStartFired) {
if (this.__dragStartSelection) {
var selectionStart = this.__dragStartSelection.selectionStart;
var selectionEnd = this.__dragStartSelection.selectionEnd;
var trailingSpace = this.__dragStartSelection.trailingSpace;
if (e.dataTransfer.dropEffect === 'move') {
this.insertChars('', null, selectionStart, selectionEnd);
this.selectionStart = this.selectionEnd = selectionStart;
this.hiddenTextarea && (this.hiddenTextarea.value = this.text);
this._updateTextarea();
this.fire('changed', { index: selectionStart, action: 'dragend' });
this.canvas.fire('text:changed', { target: this });
this.canvas.requestRenderAll();
}
else {
this.selectionStart = selectionStart;
this.selectionEnd = selectionEnd - trailingSpace;
}
this.exitEditing();
this.__lastSelected = false;
}

this.fire('dragend', { e: e });
}

this.__dragImageDisposer && this.__dragImageDisposer();
delete this.__dragImageDisposer;
delete this.__dragStartSelection;
this.__isDraggingOver = false;
},

/**
* support native like text dragging
*
* Override the `text/plain | application/fabric` types of {@link DragEvent#dataTransfer}
* in order to change the drop value or to customize styling respectively, by listening to the `drop:before` event
* https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#performing_a_drop
* @private
*/
dropHandler: function (options) {
var e = options.e;
this.__isDraggingOver = false;
// inform browser that the drop has been accepted
e.preventDefault();
var insert = e.dataTransfer.getData('text/plain');
if (insert) {
var insertAt = this.selectionStart;
var data = e.dataTransfer.types.includes('application/fabric') ?
JSON.parse(e.dataTransfer.getData('application/fabric')) :
{};
var styles = data.styles;
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
var trailingSpace = data.trailingSpace, trailing = insert[Math.max(0, insert.length - 1)];
this.canvas.discardActiveObject();
this.canvas.setActiveObject(this);
this.enterEditing(e);
var isSpace = /\s/;
var insertingOnSpace = isSpace.test(this._text[insertAt]);
var insertingAfterSpace = isSpace.test(this._text[insertAt - 1]);
var seletionStartOffset = 0;
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
// drag and drop in same instance
if (this.__dragStartSelection) {
var selectionStart = this.__dragStartSelection.selectionStart;
var selectionEnd = this.__dragStartSelection.selectionEnd;
if (insertAt > selectionStart && insertAt <= selectionEnd) {
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
insertAt = selectionStart;
trailingSpace = false;
}
else if (insertAt > selectionEnd) {
insertAt -= selectionEnd - selectionStart;
}
this.insertChars('', null, selectionStart, selectionEnd);
// prevent `dragend` from handling event
delete this.__dragStartSelection;
}
// handle spacing
if (trailingSpace && this.findLineBoundaryLeft(insertAt) < insertAt && !insertingAfterSpace
ShaMan123 marked this conversation as resolved.
Show resolved Hide resolved
&& (insertAt === this._text.length || !insertingOnSpace)) {
insert = ' ' + insert;
styles.unshift({});
seletionStartOffset = 1;
}
else if (trailingSpace && insertingOnSpace && !insertingAfterSpace) {
insertAt++;
}
// remove redundant line break
if (this._reNewline.test(trailing)
&& (this._reNewline.test(this._text[insertAt]) || insertAt === this._text.length)) {
insert = insert.trimEnd();
}
// finalize
this.insertChars(insert, styles, insertAt);
this.selectionStart = Math.min(insertAt + seletionStartOffset, this._text.length);
this.selectionEnd = Math.min(this.selectionStart + insert.length, this._text.length);
this.hiddenTextarea && (this.hiddenTextarea.value = this.text);
this._updateTextarea();
this.fire('changed', { index: insertAt + seletionStartOffset, action: 'drop' });
this.canvas.fire('text:changed', { target: this });
this.canvas.requestRenderAll();
}
},

/**
* @private
*/
Expand Down
Loading