diff --git a/src/vaadin-dialog-draggable-mixin.html b/src/vaadin-dialog-draggable-mixin.html
index a2f0e42..7120300 100644
--- a/src/vaadin-dialog-draggable-mixin.html
+++ b/src/vaadin-dialog-draggable-mixin.html
@@ -55,8 +55,14 @@
const isResizerContainer = e.target === resizerContainer;
const isResizerContainerScrollbar = e.offsetX > resizerContainer.clientWidth || e.offsetY > resizerContainer.clientHeight;
const isContentPart = e.target === this.$.overlay.$.content;
- const isDraggable = e.composedPath().some(node => {
- return node.classList && node.classList.contains(this.__dragHandleClassName || 'draggable');
+
+ const isDraggable = e.composedPath().some((node, index) => {
+ if (node.classList) {
+ const isDraggableNode = node.classList.contains(this.__dragHandleClassName || 'draggable');
+ const isDraggableLeafOnly = node.classList.contains('draggable-leaf-only');
+ const isLeafNode = index === 0;
+ return (isDraggableLeafOnly && isLeafNode) || (isDraggableNode && (!isDraggableLeafOnly || isLeafNode));
+ }
});
if ((isResizerContainer && !isResizerContainerScrollbar) || isContentPart || isDraggable) {
diff --git a/src/vaadin-dialog.html b/src/vaadin-dialog.html
index 81bb16f..204325f 100644
--- a/src/vaadin-dialog.html
+++ b/src/vaadin-dialog.html
@@ -237,7 +237,12 @@
*
* By default, only the overlay area can be used to drag the element. But,
* a child element can be marked as a draggable area by adding a
- * "`draggable`" class to it.
+ * "`draggable`" class to it, this will by default make all of its children draggable also.
+ * If you want a child element to be draggable
+ * but still have its children non-draggable (by default), mark it with
+ * "`draggable-leaf-only`" class name.
+ *
+ * @type {boolean}
*/
draggable: {
type: Boolean,
diff --git a/test/vaadin-dialog_draggable-resizable-test.html b/test/vaadin-dialog_draggable-resizable-test.html
index 6e3c498..c39396e 100644
--- a/test/vaadin-dialog_draggable-resizable-test.html
+++ b/test/vaadin-dialog_draggable-resizable-test.html
@@ -441,7 +441,10 @@
before(() => {
customElements.define('internally-draggable', class extends Polymer.Element {
static get template() {
- return Polymer.html`
draggable
`;
+ return Polymer.html`
+
+ draggable
+
`;
}
});
});
@@ -483,6 +486,56 @@
expect(Math.floor(draggedBounds.left)).to.be.eql(Math.floor(bounds.left + dx));
});
+ it('should not drag by a draggable-leaf-only if it is not the drag event target', () => {
+ const draggable = dialog.$.overlay.querySelector('internally-draggable').shadowRoot.querySelector('.draggable');
+ draggable.classList.add('draggable-leaf-only');
+ const child = draggable.firstElementChild;
+ drag(child);
+ const draggedBounds = container.getBoundingClientRect();
+ expect(Math.floor(draggedBounds.top)).to.be.eql(Math.floor(bounds.top));
+ expect(Math.floor(draggedBounds.left)).to.be.eql(Math.floor(bounds.left));
+ });
+
+ it('should drag by a draggable-leaf-only if it is directly the dragged element', () => {
+ const draggable = dialog.$.overlay.querySelector('internally-draggable').shadowRoot.querySelector('.draggable');
+ draggable.classList.add('draggable-leaf-only');
+ drag(draggable);
+ const draggedBounds = container.getBoundingClientRect();
+ expect(Math.floor(draggedBounds.top)).to.be.eql(Math.floor(bounds.top + dx));
+ expect(Math.floor(draggedBounds.left)).to.be.eql(Math.floor(bounds.left + dx));
+ });
+
+ it('should drag by a draggable-leaf-only child if it is marked as draggable', () => {
+ const draggable = dialog.$.overlay.querySelector('internally-draggable').shadowRoot.querySelector('.draggable');
+ draggable.classList.add('draggable-leaf-only');
+ const child = draggable.firstElementChild;
+ child.classList.add('draggable');
+ drag(child);
+ const draggedBounds = container.getBoundingClientRect();
+ expect(Math.floor(draggedBounds.top)).to.be.eql(Math.floor(bounds.top + dx));
+ expect(Math.floor(draggedBounds.left)).to.be.eql(Math.floor(bounds.left + dx));
+ });
+
+ it('should drag by a draggable-leaf-only child if it is marked as draggable-leaf-only', () => {
+ const draggable = dialog.$.overlay.querySelector('internally-draggable').shadowRoot.querySelector('.draggable');
+ draggable.classList.add('draggable-leaf-only');
+ const child = draggable.firstElementChild;
+ child.classList.add('draggable-leaf-only');
+ drag(child);
+ const draggedBounds = container.getBoundingClientRect();
+ expect(Math.floor(draggedBounds.top)).to.be.eql(Math.floor(bounds.top + dx));
+ expect(Math.floor(draggedBounds.left)).to.be.eql(Math.floor(bounds.left + dx));
+ });
+
+ it('should drag by a child of a draggable node ', () => {
+ const draggable = dialog.$.overlay.querySelector('internally-draggable').shadowRoot.querySelector('.draggable');
+ const child = draggable.firstElementChild;
+ drag(child);
+ const draggedBounds = container.getBoundingClientRect();
+ expect(Math.floor(draggedBounds.top)).to.be.eql(Math.floor(bounds.top + dx));
+ expect(Math.floor(draggedBounds.left)).to.be.eql(Math.floor(bounds.left + dx));
+ });
+
it('should drag and move dialog after resizing', () => {
resize(container.querySelector('.s'), 0, dx);
const bounds = container.getBoundingClientRect();