Browse Source

Merge pull request #3952 from HCL-TECH-SOFTWARE/draggable-function

Adjust draggable property to accept function
pull/3980/head
Artur Arseniev 4 years ago
committed by GitHub
parent
commit
286804c1f3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/dom_components/model/Component.js
  2. 20
      src/utils/Sorter.js
  3. 118
      test/specs/utils/Sorter.js

4
src/dom_components/model/Component.js

@ -61,10 +61,10 @@ export const keyUpdateInside = `${keyUpdate}-inside`;
* @property {Object} [attributes={}] Key-value object of the component's attributes, eg. `{ title: 'Hello' }` Default: `{}`
* @property {String} [name=''] Name of the component. Will be used, for example, in Layers and badges
* @property {Boolean} [removable=true] When `true` the component is removable from the canvas, default: `true`
* @property {Boolean|String} [draggable=true] Indicates if it's possible to drag the component inside others.
* @property {Boolean|String|Function} [draggable=true] Indicates if it's possible to drag the component inside others.
* You can also specify a query string to indentify elements,
* eg. `'.some-class[title=Hello], [data-gjs-type=column]'` means you can drag the component only inside elements
* containing `some-class` class and `Hello` title, and `column` components. Default: `true`
* containing `some-class` class and `Hello` title, and `column` components. In the case of a function, target and destination components are passed as arguments, return a Boolean to indicate if the drag is possible. Default: `true`
* @property {Boolean|String|Function} [droppable=true] Indicates if it's possible to drop other components inside. You can use
* a query string as with `draggable`. In the case of a function, target and destination components are passed as arguments, return a Boolean to indicate if the drop is possible. Default: `true`
* @property {Boolean} [badgable=true] Set to false if you don't want to see the badge (with the name) over the component. Default: `true`

20
src/utils/Sorter.js

@ -619,16 +619,24 @@ export default Backbone.View.extend({
return result;
}
// check if the source is draggable in target
// 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 (isFunction(draggable)) {
const res = draggable(srcModel, trgModel);
result.dragInfo = res;
result.draggable = res;
draggable = res;
} else {
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');
if (isFunction(droppable)) {
const res = droppable(srcModel, trgModel);
result.droppable = res;

118
test/specs/utils/Sorter.js

@ -436,56 +436,100 @@ describe('Sorter', () => {
});
describe('Valid Target with components', () => {
var parentModel;
var parentView;
var sorter;
describe('Droppable', () => {
var parentModel;
var parentView;
beforeEach(() => {
parentModel = new Component({
droppable: (srcModel, trgModel) => {
if (srcModel.getEl().className === 'canDrop') {
return true;
beforeEach(() => {
parentModel = new Component({
droppable: (srcModel, trgModel) => {
return srcModel.getEl().className === 'canDrop';
}
return false;
}
});
parentView = new ComponentTextView({
model: parentModel
});
});
parentView = new ComponentTextView({
model: parentModel
afterEach(() => {
parentView.remove();
});
sorter = new Sorter({ container: parentView.el });
});
test('Droppable function', () => {
var srcModel = new Component({
tagName: 'div',
draggable: true,
content: 'Content text',
attributes: { class: 'canDrop' }
});
var srcView = new ComponentTextView({
model: srcModel
});
expect(obj.validTarget(parentView.el, srcView.el).valid).toEqual(true);
});
afterEach(() => {
parentView.remove();
test('Not droppable function', () => {
var srcModel = new Component({
tagName: 'div',
draggable: true,
content: 'Content text',
attributes: { class: 'cannotDrop' }
});
var srcView = new ComponentTextView({
model: srcModel
});
expect(obj.validTarget(parentView.el, srcView.el).valid).toEqual(false);
});
});
test('Droppable function', () => {
var srcModel = new Component({
tagName: 'div',
draggable: true, // Can't move it
content: 'Content text', // Text inside component
attributes: { class: 'canDrop' }
});
var srcView = new ComponentTextView({
model: srcModel
});
describe('Draggable', () => {
var srcModel;
var srcView;
expect(obj.validTarget(parentView.el, srcView.el).valid).toEqual(true);
});
beforeEach(() => {
srcModel = new Component({
draggable: (srcModel, trgModel) => {
return trgModel.getEl().className === 'canDrag';
}
});
srcView = new ComponentTextView({
model: srcModel
});
});
test('Not droppable function', () => {
var srcModel = new Component({
tagName: 'div',
draggable: true,
content: 'Content text',
attributes: { class: 'cannotDrop' }
afterEach(() => {
srcView.remove();
});
var srcView = new ComponentTextView({
model: srcModel
test('Draggable function', () => {
var parentModel = new Component({
tagName: 'div',
droppable: true,
content: 'Content text',
attributes: { class: 'canDrag' }
});
var parentView = new ComponentTextView({
model: parentModel
});
expect(obj.validTarget(parentView.el, srcView.el).valid).toEqual(true);
});
expect(obj.validTarget(parentView.el, srcView.el).valid).toEqual(false);
test('Not draggable function', () => {
var parentModel = new Component({
tagName: 'div',
droppable: true,
content: 'Content text',
attributes: { class: 'cannotDrag' }
});
var parentView = new ComponentTextView({
model: parentModel
});
expect(obj.validTarget(parentView.el, srcView.el).valid).toEqual(false);
});
});
});
});

Loading…
Cancel
Save