From 607f0e5bd458ab4a11803506ecd278013f1fbc17 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Mon, 31 Jan 2022 16:15:17 +0100 Subject: [PATCH] Start canMove --- src/dom_components/index.js | 54 ++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/dom_components/index.js b/src/dom_components/index.js index 0aee7fa41..e6eace7bd 100644 --- a/src/dom_components/index.js +++ b/src/dom_components/index.js @@ -54,7 +54,7 @@ * @module Components */ import Backbone from 'backbone'; -import { isEmpty, isObject, isArray, result } from 'underscore'; +import { isEmpty, isObject, isArray, isFunction, isString, result } from 'underscore'; import defaults from './config/config'; import Component from './model/Component'; import Components from './model/Components'; @@ -646,6 +646,58 @@ export default () => { model && isEmpty(model.get('status')) && model.set('status', state); }, + /** + * Check if the component can be moved inside another. + * @param {[Component]} target The target Component is the one that is supposed to receive the source one. + * @param {[Component]|String} source The source can be another Component or an HTML string. + * @param {Number} [index] Index position. If not specified, the check will perform against appending the source to target. + * @returns {Object} `0` - Invalid source, `1` - Target doesn't accept source, `2` - Source doesn't accept target as destination + * @private + */ + canMove(target, source, index) { + const at = index || index === 0 ? index : null; + const result = { + result: false, + reason: 0, + target, + source: null, + }; + + if (!source) return result; + + const srcModel = null; + + if (!srcModel) return result; + + // Check if the target accepts the source + let droppable = target.get('droppable'); + + if (isFunction(droppable)) { + droppable = !!droppable(srcModel, target, at); + } else if (isString(droppable) || isArray(droppable)) { + const droppableStr = isArray(droppable) ? droppable.join(',') : droppable; + const srcEl = srcModel.getEl(); + droppable = srcEl?.matches(droppableStr); + } + + if (!droppable) return { ...result, reason: 1 }; + + // Check if the source is draggable in the target + let draggable = srcModel.get('draggable'); + + if (isFunction(draggable)) { + draggable = !!draggable(srcModel, target, at); + } else if (isString(draggable) || isArray(draggable)) { + const draggableStr = isArray(draggable) ? draggable.join(',') : draggable; + const targetEl = target.getEl(); + draggable = targetEl?.matches(draggableStr); + } + + if (!draggable) return { ...result, reason: 2 }; + + return { ...result, result: true }; + }, + allById() { return componentsById; },