Browse Source

Merge branch 'textable-blocks' into dev

pull/2031/head
Artur Arseniev 7 years ago
parent
commit
fc085fba01
  1. 14
      src/dom_components/view/ComponentTextView.js
  2. 13
      src/dom_components/view/ComponentView.js
  3. 169
      src/utils/Sorter.js

14
src/dom_components/view/ComponentTextView.js

@ -88,19 +88,19 @@ module.exports = ComponentView.extend({
model.set('content', content, contentOpt);
} else {
const clean = model => {
const selectable = !['text', 'default', ''].some(type =>
model.is(type)
);
const textable = !!model.get('textable');
const selectable =
!['text', 'default', ''].some(type => model.is(type)) || textable;
model.set(
{
editable: selectable && model.get('editable'),
selectable: selectable,
hoverable: selectable,
removable: textable,
draggable: textable,
highlightable: 0,
removable: 0,
draggable: 0,
copyable: 0,
toolbar: ''
copyable: textable,
...(!textable && { toolbar: '' })
},
opts
);

13
src/dom_components/view/ComponentView.js

@ -236,11 +236,14 @@ module.exports = Backbone.View.extend({
updateAttributes() {
const attrs = [];
const { model, $el, el } = this;
const defaultAttr = { 'data-gjs-type': model.get('type') || 'default' };
if (model.get('highlightable')) {
defaultAttr['data-highlightable'] = 1;
}
const defaultAttr = {
'data-gjs-type': model.get('type') || 'default',
...(model.get('highlightable') && { 'data-highlightable': 1 }),
...(model.get('textable') && {
contenteditable: 'false',
'data-gjs-textable': 'true'
})
};
// Remove all current attributes
each(el.attributes, attr => attrs.push(attr.nodeName));

169
src/utils/Sorter.js

@ -1,6 +1,6 @@
import Backbone from 'backbone';
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.$;
module.exports = Backbone.View.extend({
@ -51,6 +51,7 @@ module.exports = Backbone.View.extend({
this.canvasRelative = o.canvasRelative || 0;
this.selectOnEnd = !o.avoidSelectOnEnd;
this.scale = o.scale;
this.activeTextModel = null;
if (this.em && this.em.on) {
this.em.on('change:canvasOffset', this.udpateOffset);
@ -96,6 +97,34 @@ module.exports = Backbone.View.extend({
this.dropContent = content;
},
updateTextViewCursorPosition(e) {
const Canvas = this.em.get('Canvas');
const targetDoc = Canvas.getDocument();
let range = null;
if (targetDoc.caretRangeFromPoint) {
// Chrome
const poiner = getPointerEvent(e);
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();
range && sel.addRange(range);
},
setContentEditable(model, mode) {
if (model) {
const el = model.getEl();
if (el.contentEditable != mode) el.contentEditable = mode;
}
},
/**
* Toggle cursor while sorting
* @param {Boolean} active
@ -308,30 +337,40 @@ module.exports = Backbone.View.extend({
* Get the model of the current source element (element to drag)
* @return {Model}
*/
getSourceModel(source) {
var src = source || this.eV;
let dropContent = this.dropContent;
let dropModel = this.dropModel;
const em = this.em;
getSourceModel(source, { target, avoidChildren = 1 } = {}) {
const { em, eV } = this;
const src = source || eV;
let { dropModel, dropContent } = this;
const isTextable = src =>
src &&
target &&
src.opt.avoidChildren &&
this.isTextableActive(src, target);
if (dropContent && em) {
if (isTextable(dropModel)) {
dropModel = null;
}
if (!dropModel) {
let comps = em.get('DomComponents').getComponents();
const comps = em.get('DomComponents').getComponents();
const opts = {
avoidChildren,
avoidStore: 1,
avoidChildren: 1,
avoidUpdateStyle: 1
};
let tempModel = comps.add(dropContent, { ...opts, temporary: 1 });
const tempModel = comps.add(dropContent, { ...opts, temporary: 1 });
dropModel = comps.remove(tempModel, opts);
this.dropModel = dropModel instanceof Array ? dropModel[0] : dropModel;
if (isTextable(dropModel)) {
return this.getSourceModel(src, { target, avoidChildren: 0 });
}
}
return dropModel;
}
if (src) {
return $(src).data('model');
}
return src && $(src).data('model');
},
/**
@ -359,11 +398,11 @@ module.exports = Backbone.View.extend({
* @param {Event} e
* */
onMove(e) {
const em = this.em;
const ev = e;
const { em, onMoveClb, plh } = this;
this.moved = 1;
// Turn placeholder visibile
var plh = this.plh;
var dsp = plh.style.display;
if (!dsp || dsp === 'none') plh.style.display = 'block';
@ -385,6 +424,7 @@ module.exports = Backbone.View.extend({
this.eventMove = e;
//var targetNew = this.getTargetFromEl(e.target);
const sourceModel = this.getSourceModel();
const dims = this.dimsFromTarget(e.target, rX, rY);
const target = this.target;
const targetModel = this.getTargetModel(target);
@ -392,26 +432,39 @@ module.exports = Backbone.View.extend({
if (!targetModel) plh.style.display = 'none';
this.lastDims = dims;
var pos = this.findPosition(dims, rX, rY);
// 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');
}
const pos = this.findPosition(dims, rX, rY);
if (this.isTextableActive(sourceModel, targetModel)) {
this.activeTextModel = targetModel;
this.setContentEditable(targetModel, true);
plh.style.display = 'none';
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.trigger('sorter:drag', {
@ -424,6 +477,15 @@ module.exports = Backbone.View.extend({
});
},
isTextableActive(src, trg) {
return src && src.get('textable') && trg && trg.is('text');
},
disableTextable() {
const { activeTextModel } = this;
activeTextModel && activeTextModel.getView().disableEditing();
},
/**
* Returns true if the elements is in flow, so is not in flow where
* for example the component is with float:left
@ -495,9 +557,9 @@ module.exports = Backbone.View.extend({
* @return {Boolean}
*/
validTarget(trg, src) {
let srcModel = this.getSourceModel(src);
const trgModel = this.getTargetModel(trg);
const srcModel = this.getSourceModel(src, { target: trgModel });
src = srcModel && srcModel.view && srcModel.view.el;
let trgModel = this.getTargetModel(trg);
trg = trgModel && trgModel.view && trgModel.view.el;
let result = {
valid: true,
@ -512,21 +574,23 @@ module.exports = Backbone.View.extend({
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
let droppable = trgModel.get('droppable');
droppable = droppable instanceof Backbone.Collection ? 1 : droppable;
droppable = droppable instanceof Array ? droppable.join(', ') : droppable;
result.dropInfo = droppable;
droppable = isString(droppable) ? this.matches(src, droppable) : droppable;
droppable =
draggable && this.isTextableActive(srcModel, trgModel) ? 1 : droppable;
result.droppable = droppable;
// 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;
if (!droppable || !draggable) {
result.valid = false;
}
@ -914,7 +978,6 @@ module.exports = Backbone.View.extend({
* @return void
* */
endMove(e) {
var created;
const moved = [null];
const docs = this.getDocuments();
const container = this.getContainerEl();
@ -923,10 +986,7 @@ module.exports = Backbone.View.extend({
off(container, 'mousemove dragover', this.onMove);
off(docs, 'mouseup dragend touchend', this.endMove);
off(docs, 'keydown', this.rollback);
//this.$document.off('mouseup', this.endMove);
//this.$document.off('keydown', this.rollback);
this.plh.style.display = 'none';
var clsReg = new RegExp('(?:^|\\s)' + this.freezeClass + '(?!\\S)', 'gi');
let src = this.eV;
if (src && this.selectOnEnd) {
@ -953,6 +1013,7 @@ module.exports = Backbone.View.extend({
this.dragHelper = null;
}
this.disableTextable();
this.selectTargetModel();
this.toggleSortCursor();
@ -967,7 +1028,7 @@ module.exports = Backbone.View.extend({
* @param {Object} pos Object with position coordinates
* */
move(dst, src, pos) {
var em = this.em;
const { em, activeTextModel } = this;
const srcEl = getElement(src);
em && em.trigger('component:dragEnd:before', dst, srcEl, pos); // @depricated
var warns = [];
@ -981,8 +1042,9 @@ module.exports = Backbone.View.extend({
var dropInfo = validResult.dropInfo;
var dragInfo = validResult.dragInfo;
var dropContent = this.dropContent;
droppable =
validResult.trgModel instanceof Backbone.Collection ? 1 : droppable;
const { trgModel } = validResult;
droppable = trgModel instanceof Backbone.Collection ? 1 : droppable;
const isTextableActive = this.isTextableActive(model, trgModel);
if (targetCollection && droppable && draggable) {
index = pos.method === 'after' ? index + 1 : index;
@ -993,7 +1055,7 @@ module.exports = Backbone.View.extend({
opts.temporary = 1;
modelTemp = targetCollection.add({}, { ...opts });
if (model) {
if (model.collection) {
modelToDrop = model.collection.remove(model, { temporary: 1 });
}
} else {
@ -1002,7 +1064,18 @@ module.exports = Backbone.View.extend({
opts.avoidUpdateStyle = 1;
}
created = targetCollection.add(modelToDrop, opts);
if (isTextableActive) {
const viewActive = activeTextModel.getView();
activeTextModel.trigger('active');
const { activeRte } = viewActive;
const modelEl = model.getEl();
model.getView().render();
modelEl.setAttribute('data-gjs-textable', 'true');
const { outerHTML } = modelEl;
activeRte.insertHTML && activeRte.insertHTML(outerHTML);
} else {
created = targetCollection.add(modelToDrop, opts);
}
if (!dropContent) {
targetCollection.remove(modelTemp);

Loading…
Cancel
Save