From f340b7d9c5aaa1bb44e4bdb162440e39289eeca0 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Wed, 10 Apr 2019 23:48:17 +0200 Subject: [PATCH] Place the component at the index based on childNodes --- src/canvas/view/CanvasView.js | 14 +++++++++-- .../view/ComponentTextNodeView.js | 4 +++- src/utils/Sorter.js | 24 ++++++++++++------- src/utils/mixins.js | 8 +++++++ 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/canvas/view/CanvasView.js b/src/canvas/view/CanvasView.js index 8c9482adf..c73265578 100644 --- a/src/canvas/view/CanvasView.js +++ b/src/canvas/view/CanvasView.js @@ -1,5 +1,5 @@ import Backbone from 'backbone'; -import { on, off, getElement, getKeyChar } from 'utils/mixins'; +import { on, off, getElement, getKeyChar, isTextNode } from 'utils/mixins'; const FrameView = require('./FrameView'); const $ = Backbone.$; let timerZoom; @@ -294,7 +294,16 @@ module.exports = Backbone.View.extend({ * @return {Object} */ offset(el) { - var rect = el.getBoundingClientRect(); + let rectText; + + if (isTextNode(el)) { + const range = document.createRange(); + range.selectNode(el); + rectText = range.getBoundingClientRect(); + range.detach(); + } + + var rect = rectText || el.getBoundingClientRect(); var docBody = el.ownerDocument.body; return { top: rect.top + docBody.scrollTop, @@ -364,6 +373,7 @@ module.exports = Backbone.View.extend({ * @private */ getElementOffsets(el) { + if (!el || isTextNode(el)) return {}; const result = {}; const styles = window.getComputedStyle(el); [ diff --git a/src/dom_components/view/ComponentTextNodeView.js b/src/dom_components/view/ComponentTextNodeView.js index 6171db97e..f2b29ff73 100644 --- a/src/dom_components/view/ComponentTextNodeView.js +++ b/src/dom_components/view/ComponentTextNodeView.js @@ -1,6 +1,8 @@ module.exports = require('backbone').View.extend({ initialize() { - this.model.view = this; + const { $el, model } = this; + $el.data('model', model); + model.view = this; }, _createElement() { return document.createTextNode(this.model.get('content')); diff --git a/src/utils/Sorter.js b/src/utils/Sorter.js index bfda067e9..f8874b0fa 100644 --- a/src/utils/Sorter.js +++ b/src/utils/Sorter.js @@ -1,6 +1,13 @@ import Backbone from 'backbone'; -import { isString, isFunction, isArray, result } from 'underscore'; -import { on, off, matches, getElement, getPointerEvent } from 'utils/mixins'; +import { isString, isFunction, isArray, result, indexOf } from 'underscore'; +import { + on, + off, + matches, + getElement, + getPointerEvent, + isTextNode +} from 'utils/mixins'; const $ = Backbone.$; module.exports = Backbone.View.extend({ @@ -514,7 +521,8 @@ module.exports = Backbone.View.extend({ * @private */ styleInFlow(el, parent) { - const style = el.style; + if (isTextNode(el)) return; + const style = el.style || {}; const $el = $(el); const $parent = parent && $(parent); @@ -816,7 +824,7 @@ module.exports = Backbone.View.extend({ for (var i = 0, len = ch.length; i < len; i++) { var el = ch[i]; - if (!this.matches(el, this.itemSel)) { + if (!isTextNode(el) && !this.matches(el, this.itemSel)) { continue; } @@ -827,8 +835,7 @@ module.exports = Backbone.View.extend({ else if (dir == 'h') dir = false; else dir = this.isInFlow(el, trg); - dim.push(dir); - dim.push(el); + dim.push(dir, el, indexOf(trg.childNodes, el)); dims.push(dim); } @@ -865,7 +872,7 @@ module.exports = Backbone.View.extend({ * @retun {Object} * */ findPosition(dims, posX, posY) { - var result = { index: 0, method: 'before' }; + var result = { index: 0, indexEl: 0, method: 'before' }; var leftLimit = 0, xLimit = 0, dimRight = 0, @@ -893,6 +900,7 @@ module.exports = Backbone.View.extend({ ) continue; result.index = i; + result.indexEl = dim[6]; // If it's not in flow (like 'float' element) if (!dim[4]) { if (posY < dimDown) yLimit = dimDown; @@ -1032,7 +1040,7 @@ module.exports = Backbone.View.extend({ const srcEl = getElement(src); em && em.trigger('component:dragEnd:before', dst, srcEl, pos); // @depricated var warns = []; - var index = pos.index; + var index = pos.indexEl; var modelToDrop, modelTemp, created; var validResult = this.validTarget(dst, srcEl); var targetCollection = $(dst).data('collection'); diff --git a/src/utils/mixins.js b/src/utils/mixins.js index add8ac8bb..be406353c 100644 --- a/src/utils/mixins.js +++ b/src/utils/mixins.js @@ -110,6 +110,13 @@ const getElement = el => { } }; +/** + * Check if element is a text node + * @param {HTMLElement} el + * @return {Boolean} + */ +const isTextNode = el => el && el.nodeType === 3; + /** * Ensure to fetch the model from the input argument * @param {HTMLElement|Component} el Component or HTML element @@ -147,6 +154,7 @@ export { matches, getModel, camelCase, + isTextNode, getKeyCode, getKeyChar, getElement,