|
|
@ -1,6 +1,6 @@ |
|
|
import Backbone from 'backbone'; |
|
|
import Backbone from 'backbone'; |
|
|
import { isString, isFunction, isArray, result } from 'underscore'; |
|
|
import { isString, isFunction, isArray, result } from 'underscore'; |
|
|
import { on, off, matches, getElement } from 'utils/mixins'; |
|
|
import { on, off, matches, getElement, getPointerEvent } from 'utils/mixins'; |
|
|
const $ = Backbone.$; |
|
|
const $ = Backbone.$; |
|
|
|
|
|
|
|
|
module.exports = Backbone.View.extend({ |
|
|
module.exports = Backbone.View.extend({ |
|
|
@ -51,6 +51,7 @@ module.exports = Backbone.View.extend({ |
|
|
this.canvasRelative = o.canvasRelative || 0; |
|
|
this.canvasRelative = o.canvasRelative || 0; |
|
|
this.selectOnEnd = !o.avoidSelectOnEnd; |
|
|
this.selectOnEnd = !o.avoidSelectOnEnd; |
|
|
this.scale = o.scale; |
|
|
this.scale = o.scale; |
|
|
|
|
|
this.activeTextModel = null; |
|
|
|
|
|
|
|
|
if (this.em && this.em.on) { |
|
|
if (this.em && this.em.on) { |
|
|
this.em.on('change:canvasOffset', this.udpateOffset); |
|
|
this.em.on('change:canvasOffset', this.udpateOffset); |
|
|
@ -96,6 +97,39 @@ module.exports = Backbone.View.extend({ |
|
|
this.dropContent = content; |
|
|
this.dropContent = content; |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
updateTextViewCursorPosition(e) { |
|
|
|
|
|
const { em } = this; |
|
|
|
|
|
const Canvas = em.get('Canvas'); |
|
|
|
|
|
const targetDoc = Canvas.getDocument(); |
|
|
|
|
|
const poiner = getPointerEvent(e); |
|
|
|
|
|
let range = null; |
|
|
|
|
|
|
|
|
|
|
|
if (targetDoc.caretRangeFromPoint) { |
|
|
|
|
|
// Chrome
|
|
|
|
|
|
range = targetDoc.caretRangeFromPoint(poiner.clientX, poiner.clientY); |
|
|
|
|
|
} else if (e.rangeParent) { |
|
|
|
|
|
// Firefox
|
|
|
|
|
|
range = targetDoc.createRange(); |
|
|
|
|
|
range.setStart(e.rangeParent, e.rangeOffset); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const sel = Canvas.getWindow().getSelection(); |
|
|
|
|
|
Canvas.getFrameEl().focus(); |
|
|
|
|
|
sel.removeAllRanges(); |
|
|
|
|
|
sel.addRange(range); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
disableEditingOn(model) { |
|
|
|
|
|
model && model.getView().disableEditing(); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
setContentEditable(model, mode) { |
|
|
|
|
|
if (model) { |
|
|
|
|
|
const el = model.getEl(); |
|
|
|
|
|
if (el.contentEditable != mode) el.contentEditable = mode; |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Toggle cursor while sorting |
|
|
* Toggle cursor while sorting |
|
|
* @param {Boolean} active |
|
|
* @param {Boolean} active |
|
|
@ -359,7 +393,8 @@ module.exports = Backbone.View.extend({ |
|
|
* @param {Event} e |
|
|
* @param {Event} e |
|
|
* */ |
|
|
* */ |
|
|
onMove(e) { |
|
|
onMove(e) { |
|
|
const em = this.em; |
|
|
const ev = e; |
|
|
|
|
|
const { em, onMoveClb, activeTextModel } = this; |
|
|
this.moved = 1; |
|
|
this.moved = 1; |
|
|
|
|
|
|
|
|
// Turn placeholder visibile
|
|
|
// Turn placeholder visibile
|
|
|
@ -385,6 +420,7 @@ module.exports = Backbone.View.extend({ |
|
|
this.eventMove = e; |
|
|
this.eventMove = e; |
|
|
|
|
|
|
|
|
//var targetNew = this.getTargetFromEl(e.target);
|
|
|
//var targetNew = this.getTargetFromEl(e.target);
|
|
|
|
|
|
const sourceModel = this.getSourceModel(); |
|
|
const dims = this.dimsFromTarget(e.target, rX, rY); |
|
|
const dims = this.dimsFromTarget(e.target, rX, rY); |
|
|
const target = this.target; |
|
|
const target = this.target; |
|
|
const targetModel = this.getTargetModel(target); |
|
|
const targetModel = this.getTargetModel(target); |
|
|
@ -392,26 +428,39 @@ module.exports = Backbone.View.extend({ |
|
|
if (!targetModel) plh.style.display = 'none'; |
|
|
if (!targetModel) plh.style.display = 'none'; |
|
|
|
|
|
|
|
|
this.lastDims = dims; |
|
|
this.lastDims = dims; |
|
|
var pos = this.findPosition(dims, rX, rY); |
|
|
const pos = this.findPosition(dims, rX, rY); |
|
|
// If there is a significant changes with the pointer
|
|
|
|
|
|
if ( |
|
|
if (this.isTextableActive(sourceModel, targetModel)) { |
|
|
!this.lastPos || |
|
|
this.activeTextModel = targetModel; |
|
|
(this.lastPos.index != pos.index || this.lastPos.method != pos.method) |
|
|
this.setContentEditable(targetModel, true); |
|
|
) { |
|
|
|
|
|
this.movePlaceholder(this.plh, dims, pos, this.prevTargetDim); |
|
|
|
|
|
if (!this.$plh) this.$plh = $(this.plh); |
|
|
|
|
|
|
|
|
|
|
|
// With canvasRelative the offset is calculated automatically for
|
|
|
|
|
|
// each element
|
|
|
|
|
|
if (!this.canvasRelative) { |
|
|
|
|
|
if (this.offTop) this.$plh.css('top', '+=' + this.offTop + 'px'); |
|
|
|
|
|
if (this.offLeft) this.$plh.css('left', '+=' + this.offLeft + 'px'); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plh.style.display = 'none'; |
|
|
this.lastPos = pos; |
|
|
this.lastPos = pos; |
|
|
|
|
|
this.updateTextViewCursorPosition(ev); |
|
|
|
|
|
} else { |
|
|
|
|
|
this.disableTextable(); |
|
|
|
|
|
this.activeTextModel = null; |
|
|
|
|
|
|
|
|
|
|
|
// If there is a significant changes with the pointer
|
|
|
|
|
|
if ( |
|
|
|
|
|
!this.lastPos || |
|
|
|
|
|
(this.lastPos.index != pos.index || this.lastPos.method != pos.method) |
|
|
|
|
|
) { |
|
|
|
|
|
this.movePlaceholder(this.plh, dims, pos, this.prevTargetDim); |
|
|
|
|
|
if (!this.$plh) this.$plh = $(this.plh); |
|
|
|
|
|
|
|
|
|
|
|
// With canvasRelative the offset is calculated automatically for
|
|
|
|
|
|
// each element
|
|
|
|
|
|
if (!this.canvasRelative) { |
|
|
|
|
|
if (this.offTop) this.$plh.css('top', '+=' + this.offTop + 'px'); |
|
|
|
|
|
if (this.offLeft) this.$plh.css('left', '+=' + this.offLeft + 'px'); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.lastPos = pos; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (typeof this.onMoveClb === 'function') this.onMoveClb(e); |
|
|
isFunction(onMoveClb) && onMoveClb(e); |
|
|
|
|
|
|
|
|
em && |
|
|
em && |
|
|
em.trigger('sorter:drag', { |
|
|
em.trigger('sorter:drag', { |
|
|
@ -424,6 +473,15 @@ module.exports = Backbone.View.extend({ |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
isTextableActive(src, trg) { |
|
|
|
|
|
return src && src.get('textable') && trg && trg.is('text'); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
disableTextable() { |
|
|
|
|
|
const { activeTextModel } = this; |
|
|
|
|
|
activeTextModel && this.setContentEditable(activeTextModel, false); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Returns true if the elements is in flow, so is not in flow where |
|
|
* Returns true if the elements is in flow, so is not in flow where |
|
|
* for example the component is with float:left |
|
|
* for example the component is with float:left |
|
|
@ -512,20 +570,35 @@ module.exports = Backbone.View.extend({ |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// check if the source is draggable in target
|
|
|
|
|
|
let draggable = srcModel.get('draggable'); |
|
|
|
|
|
draggable = draggable instanceof Array ? draggable.join(', ') : draggable; |
|
|
|
|
|
result.dragInfo = draggable; |
|
|
|
|
|
draggable = isString(draggable) ? this.matches(trg, draggable) : draggable; |
|
|
|
|
|
result.draggable = draggable; |
|
|
|
|
|
|
|
|
// Check if the target could accept the source
|
|
|
// Check if the target could accept the source
|
|
|
let droppable = trgModel.get('droppable'); |
|
|
let droppable = trgModel.get('droppable'); |
|
|
droppable = droppable instanceof Backbone.Collection ? 1 : droppable; |
|
|
droppable = droppable instanceof Backbone.Collection ? 1 : droppable; |
|
|
droppable = droppable instanceof Array ? droppable.join(', ') : droppable; |
|
|
droppable = droppable instanceof Array ? droppable.join(', ') : droppable; |
|
|
result.dropInfo = droppable; |
|
|
result.dropInfo = droppable; |
|
|
droppable = isString(droppable) ? this.matches(src, droppable) : droppable; |
|
|
droppable = isString(droppable) ? this.matches(src, droppable) : droppable; |
|
|
|
|
|
droppable = |
|
|
|
|
|
trgModel.is('text') && draggable && srcModel.get('textable') |
|
|
|
|
|
? 1 |
|
|
|
|
|
: droppable; |
|
|
result.droppable = droppable; |
|
|
result.droppable = droppable; |
|
|
|
|
|
|
|
|
// check if the source is draggable in target
|
|
|
console.log( |
|
|
let draggable = srcModel.get('draggable'); |
|
|
`trgModel.is('text')`, |
|
|
draggable = draggable instanceof Array ? draggable.join(', ') : draggable; |
|
|
trgModel.is('text'), |
|
|
result.dragInfo = draggable; |
|
|
`srcModel.get('textable')`, |
|
|
draggable = isString(draggable) ? this.matches(trg, draggable) : draggable; |
|
|
srcModel.get('textable'), |
|
|
result.draggable = draggable; |
|
|
'droppable', |
|
|
|
|
|
droppable, |
|
|
|
|
|
'draggable', |
|
|
|
|
|
draggable |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
if (!droppable || !draggable) { |
|
|
if (!droppable || !draggable) { |
|
|
result.valid = false; |
|
|
result.valid = false; |
|
|
@ -953,6 +1026,7 @@ module.exports = Backbone.View.extend({ |
|
|
this.dragHelper = null; |
|
|
this.dragHelper = null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.disableTextable(); |
|
|
this.selectTargetModel(); |
|
|
this.selectTargetModel(); |
|
|
this.toggleSortCursor(); |
|
|
this.toggleSortCursor(); |
|
|
|
|
|
|
|
|
@ -967,7 +1041,7 @@ module.exports = Backbone.View.extend({ |
|
|
* @param {Object} pos Object with position coordinates |
|
|
* @param {Object} pos Object with position coordinates |
|
|
* */ |
|
|
* */ |
|
|
move(dst, src, pos) { |
|
|
move(dst, src, pos) { |
|
|
var em = this.em; |
|
|
const { em, activeTextModel } = this; |
|
|
const srcEl = getElement(src); |
|
|
const srcEl = getElement(src); |
|
|
em && em.trigger('component:dragEnd:before', dst, srcEl, pos); // @depricated
|
|
|
em && em.trigger('component:dragEnd:before', dst, srcEl, pos); // @depricated
|
|
|
var warns = []; |
|
|
var warns = []; |
|
|
@ -981,8 +1055,21 @@ module.exports = Backbone.View.extend({ |
|
|
var dropInfo = validResult.dropInfo; |
|
|
var dropInfo = validResult.dropInfo; |
|
|
var dragInfo = validResult.dragInfo; |
|
|
var dragInfo = validResult.dragInfo; |
|
|
var dropContent = this.dropContent; |
|
|
var dropContent = this.dropContent; |
|
|
droppable = |
|
|
const { trgModel } = validResult; |
|
|
validResult.trgModel instanceof Backbone.Collection ? 1 : droppable; |
|
|
droppable = trgModel instanceof Backbone.Collection ? 1 : droppable; |
|
|
|
|
|
const modelIsTextable = model.get('textable'); |
|
|
|
|
|
const targetIsTextView = trgModel && trgModel.is('text'); |
|
|
|
|
|
|
|
|
|
|
|
console.log( |
|
|
|
|
|
'droppable', |
|
|
|
|
|
droppable, |
|
|
|
|
|
'draggable', |
|
|
|
|
|
draggable, |
|
|
|
|
|
'modelIsTextable', |
|
|
|
|
|
modelIsTextable, |
|
|
|
|
|
'targetIsTextView', |
|
|
|
|
|
targetIsTextView |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
if (targetCollection && droppable && draggable) { |
|
|
if (targetCollection && droppable && draggable) { |
|
|
index = pos.method === 'after' ? index + 1 : index; |
|
|
index = pos.method === 'after' ? index + 1 : index; |
|
|
@ -993,7 +1080,7 @@ module.exports = Backbone.View.extend({ |
|
|
opts.temporary = 1; |
|
|
opts.temporary = 1; |
|
|
modelTemp = targetCollection.add({}, { ...opts }); |
|
|
modelTemp = targetCollection.add({}, { ...opts }); |
|
|
|
|
|
|
|
|
if (model) { |
|
|
if (model.collection) { |
|
|
modelToDrop = model.collection.remove(model, { temporary: 1 }); |
|
|
modelToDrop = model.collection.remove(model, { temporary: 1 }); |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
@ -1002,7 +1089,14 @@ module.exports = Backbone.View.extend({ |
|
|
opts.avoidUpdateStyle = 1; |
|
|
opts.avoidUpdateStyle = 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
created = targetCollection.add(modelToDrop, opts); |
|
|
if (targetIsTextView && modelIsTextable) { |
|
|
|
|
|
const viewActive = activeTextModel.getView(); |
|
|
|
|
|
activeTextModel.trigger('active'); |
|
|
|
|
|
const { activeRte } = viewActive; |
|
|
|
|
|
activeRte.insertHTML && activeRte.insertHTML(model.toHTML()); |
|
|
|
|
|
} else { |
|
|
|
|
|
created = targetCollection.add(modelToDrop, opts); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (!dropContent) { |
|
|
if (!dropContent) { |
|
|
targetCollection.remove(modelTemp); |
|
|
targetCollection.remove(modelTemp); |
|
|
@ -1010,6 +1104,10 @@ module.exports = Backbone.View.extend({ |
|
|
this.dropContent = null; |
|
|
this.dropContent = null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (targetIsTextView && modelIsTextable) { |
|
|
|
|
|
this.disableEditingOn(activeTextModel); // TODO disableEditingOn is used only here
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// This will cause to recalculate children dimensions
|
|
|
// This will cause to recalculate children dimensions
|
|
|
this.prevTarget = null; |
|
|
this.prevTarget = null; |
|
|
} else { |
|
|
} else { |
|
|
|