Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui5-dialog): introduce draggable property #2269

Merged
merged 1 commit into from
Oct 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/base/src/util/isValidPropertyName.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const allowList = [
"disabled",
"title",
"hidden",
"draggable",
];

/**
Expand Down
5 changes: 4 additions & 1 deletion packages/main/src/Dialog.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{{>include "./Popup.hbs"}}

{{#*inline "beforeContent"}}
<header class="ui5-popup-header-root" id="ui5-popup-header">
<header
class="ui5-popup-header-root"
id="ui5-popup-header"
@mousedown="{{_onDragMouseDown}}">
{{#if header.length }}
<slot name="header"></slot>
{{else}}
Expand Down
132 changes: 126 additions & 6 deletions packages/main/src/Dialog.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";
import { isPhone, isDesktop } from "@ui5/webcomponents-base/dist/Device.js";
import Popup from "./Popup.js";

// Template
Expand Down Expand Up @@ -52,7 +52,7 @@ const metadata = {
/**
* Determines whether the <code>ui5-dialog</code> should be stretched to fullscreen.
* <br><br>
* <b>Note:</b> The <code>ui5-dialog</code> will be stretched to aproximetly
* <b>Note:</b> The <code>ui5-dialog</code> will be stretched to approximately
* 90% of the viewport.
*
* @type {boolean}
Expand All @@ -63,12 +63,32 @@ const metadata = {
type: Boolean,
},

/**
* Determines whether the <code>ui5-dialog</code> is draggable.
* If this property is set to true, the Dialog will be draggable by its header.
* <br><br>
* <b>Note:</b> The <code>ui5-dialog</code> can be draggable only in desktop mode.
* @defaultvalue false
* @since 1.0.0-rc.9
* @public
georgimkv marked this conversation as resolved.
Show resolved Hide resolved
*/
draggable: {
type: Boolean,
},

/**
* @private
*/
onPhone: {
type: Boolean,
},

/**
* @private
*/
onDesktop: {
type: Boolean,
},
},
};

Expand All @@ -89,6 +109,9 @@ const metadata = {
* <h3>Structure</h3>
* A <code>ui5-dialog</code> consists of a header, content, and a footer for action buttons.
* The <code>ui5-dialog</code> is usually displayed at the center of the screen.
* Its position can be changed by the user. To enable this, you need to set the property <code>draggable</code> accordingly.


*
* <h3>Responsive Behavior</h3>
* The <code>stretch</code> property can be used to stretch the
Expand Down Expand Up @@ -121,10 +144,6 @@ class Dialog extends Popup {
return [PopupsCommonCss, dialogCSS];
}

onBeforeRendering() {
this.onPhone = isPhone();
}

get isModal() { // Required by Popup.js
return true;
}
Expand All @@ -147,6 +166,107 @@ class Dialog extends Popup {
},
};
}

onBeforeRendering() {
this.onPhone = isPhone();
this.onDesktop = isDesktop();
}

onEnterDOM() {
this._dragMouseMoveHandler = this._onDragMouseMove.bind(this);
this._dragMouseUpHandler = this._onDragMouseUp.bind(this);
}

onExitDOM() {
this._dragMouseMoveHandler = null;
this._dragMouseUpHandler = null;
}

/**
* Event handlers
*/
_onDragMouseDown(event) {
if (!(this.draggable && this.onDesktop)) {
return;
}

// only allow dragging on the header's whitespace
if (!event.target.classList.contains("ui5-popup-header-root")
&& event.target.getAttribute("slot") !== "header") {
return;
}

event.preventDefault();

const {
top,
left,
} = this.getBoundingClientRect();
const {
width,
height,
} = window.getComputedStyle(this);

Object.assign(this.style, {
transform: "none",
top: `${top}px`,
left: `${left}px`,
width: `${Math.round(Number(width) * 100) / 100}px`,
height: `${Math.round(Number(height) * 100) / 100}px`,
});

this._x = event.clientX;
this._y = event.clientY;

this._attachDragHandlers();
}

_onDragMouseMove(event) {
event.preventDefault();

const calcX = this._x - event.clientX;
const calcY = this._y - event.clientY;
const {
left,
top,
} = this.getBoundingClientRect();


Object.assign(this.style, {
left: `${Math.floor(left - calcX)}px`,
top: `${Math.floor(top - calcY)}px`,
});

this._x = event.clientX;
this._y = event.clientY;
}

_onDragMouseUp() {
this._x = null;
this._y = null;

this._detachDragHandlers();
}

_attachDragHandlers() {
window.addEventListener("mousemove", this._dragMouseMoveHandler);
window.addEventListener("mouseup", this._dragMouseUpHandler);
this.addEventListener("ui5-before-close", this._recenter);
}

_detachDragHandlers() {
window.removeEventListener("mousemove", this._dragMouseMoveHandler);
window.removeEventListener("mouseup", this._dragMouseUpHandler);
}

_recenter() {
Object.assign(this.style, {
top: "",
left: "",
transform: "",
});
this.removeEventListener("ui5-before-close", this._recenter);
}
}

Dialog.define();
Expand Down
9 changes: 9 additions & 0 deletions packages/main/src/themes/Dialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@
max-width: 100vw;
}

:host([draggable]) .ui5-popup-header-root,
:host([draggable]) ::slotted([slot="header"]) {
cursor: move;
}

:host([draggable]) .ui5-popup-header-root * {
cursor: auto;
}

.ui5-popup-root {
display: flex;
flex-direction: column;
Expand Down
31 changes: 24 additions & 7 deletions packages/main/test/pages/Dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,15 @@
<br>
<br>
<ui5-button id="empty-open">Open empty dialog (no focusable element)</ui5-button>
<br><br>
<br>
<br>
<ui5-button id="wide-open">Open wide dialog</ui5-button>
<br><br>
<br>
<br>
<ui5-button id="wide-open2">Open wide dialog 2</ui5-button>
<br><br>
<br>
<br>
<ui5-button id="draggable-open">Open draggable dialog</ui5-button>

<ui5-block-layer></ui5-block-layer>

Expand Down Expand Up @@ -185,6 +189,17 @@
</div>
</ui5-dialog>

<ui5-dialog id="draggable-dialog" draggable>
<div slot="header" style="flex: 1 0 0; height: 2.5rem;">Draggable dialog</div>

<p>Move this dialog around the screen by dragging it by its header.</p>
<p>This feature available only on Desktop.</p>

<div slot="footer" style="display: flex; justify-content: flex-end; width: 100%; padding: .25rem 1rem;">
<ui5-button id="draggable-close" design="Emphasized">OK</ui5-button>
</div>
</ui5-dialog>

<ui5-popover header-text="My Heading" id="pop" style="width: 300px" placement-type="Top">
<!-- <div slot="header">
Hello World
Expand Down Expand Up @@ -247,7 +262,6 @@
<ui5-dialog id="empty-dialog">Empty</ui5-dialog>

<script>

let preventClosing = true;

btnOpenDialog.addEventListener("click", function () {
Expand Down Expand Up @@ -297,9 +311,12 @@
bigDangerPop.openBy(bigDanger);
});

window["empty-open"].addEventListener("click", function (event) { window["empty-dialog"].open(); });
window["wide-open"].addEventListener("click", function (event) { window["wide-dialog"].open(); });
window["wide-open2"].addEventListener("click", function (event) { window["wide-dialog2"].open(); });
window["empty-open"].addEventListener("click", function () { window["empty-dialog"].open(); });
window["wide-open"].addEventListener("click", function () { window["wide-dialog"].open(); });
window["wide-open2"].addEventListener("click", function () { window["wide-dialog2"].open(); });
window["draggable-open"].addEventListener("click", function () { window["draggable-dialog"].open(); });
window["draggable-close"].addEventListener("click", function () { window["draggable-dialog"].close(); });

</script>
</body>

Expand Down
37 changes: 35 additions & 2 deletions packages/main/test/specs/Dialog.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ describe("Dialog general interaction", () => {
btnOpenDialog.click();
select.click();

const dialogZIndex = parseInt(browser.$("#dialog").getCSSProperty('z-index').value);
const popoverZIndex = parseInt(browser.$(`.${select.getProperty("_id")}`).shadow$("ui5-responsive-popover").getCSSProperty('z-index').value);
const dialogZIndex = parseInt(browser.$("#dialog").getCSSProperty("z-index").value);
const popoverZIndex = parseInt(browser.$(`.${select.getProperty("_id")}`).shadow$("ui5-responsive-popover").getCSSProperty("z-index").value);

assert.ok(popoverZIndex > dialogZIndex, "Popover is above dialog.");
});
Expand All @@ -47,6 +47,39 @@ describe("Dialog general interaction", () => {

assert.ok(!browser.$("ui5-static-area").length, "No static area.");
});

it("draggable", () => {
browser.url("http://localhost:8080/test-resources/pages/Dialog.html");

const openDraggableDialogButton = browser.$("#draggable-open");
openDraggableDialogButton.click();

const dialog = browser.$("#draggable-dialog");
const topBeforeDragging = parseInt(dialog.getCSSProperty("top").value);
const leftBeforeDragging = parseInt(dialog.getCSSProperty("left").value);

const header = browser.$("#draggable-dialog").shadow$(".ui5-popup-header-root");

header.dragAndDrop({ x: -200, y: -200 });

const topAfterDragging = parseInt(dialog.getCSSProperty("top").value);
const leftAfterDragging = parseInt(dialog.getCSSProperty("left").value);

assert.notStrictEqual(topBeforeDragging, topAfterDragging, "top position has changed");
assert.notStrictEqual(leftBeforeDragging, leftAfterDragging, "left position has changed");

browser.keys("Enter");

openDraggableDialogButton.click();

const topAfterReopening = parseInt(dialog.getCSSProperty("top").value);
const leftAfterReopening = parseInt(dialog.getCSSProperty("left").value);

assert.strictEqual(topBeforeDragging, topAfterReopening, "top position has been reset back to initial");
assert.strictEqual(leftBeforeDragging, leftAfterReopening, "left position has been reset back to initial");

browser.keys("esc");
});
});


Expand Down