Skip to content

Commit 47a8c17

Browse files
EdgarChenmoz-wptsync-bot
authored andcommitted
Make buttons draggable when a drag is started from the button itself
We already support dragging a button when the drag starts from its text content. Differential Revision: https://phabricator.services.mozilla.com/D272337 bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=568313 gecko-commit: e2c75ec8ecea40f3fd07d287da82b06d19a633e0 gecko-reviewers: masayuki
1 parent 5ae09b7 commit 47a8c17

10 files changed

+716
-124
lines changed

html/editing/dnd/interactiveelements/button_inside_draggable_element.html

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,68 @@
1313
</head>
1414
<body>
1515

16-
<p>Press your mouse button down on the orange block and drag downwards. It should <strong>not</strong> drag the block or text.</p>
17-
<div draggable="true" id="element">
16+
<p>Press your mouse button down on the orange block and drag downwards. It should drag the draggable element.</p>
17+
<p>Press your mouse button down on the text and drag rightward. It should drag the draggable element.</p>
18+
<div draggable="true" id="outer">
1819
<button id="inner">Dummy text</button>
1920
</div>
2021

2122
<script>
22-
const element = document.getElementById("element");
23+
const outer = document.getElementById("outer");
2324
const inner = document.getElementById("inner");
2425

25-
promise_test(t => {
26-
return new Promise((resolve, reject) => {
27-
let didReceiveDragStart = false;
28-
29-
const dragStartListener = ev => {
30-
ev.preventDefault();
31-
didReceiveDragStart = true;
32-
};
33-
element.addEventListener("dragstart", dragStartListener, { once: true });
34-
t.add_cleanup(() => element.removeEventListener("dragstart", dragStartListener));
35-
36-
element.addEventListener("mouseup", () => {
37-
resolve(didReceiveDragStart);
38-
}, { once: true });
39-
40-
const centerH = inner.getBoundingClientRect().height / 2;
41-
new test_driver.Actions()
42-
// Move pointer to the center of the top-border.
43-
.pointerMove(0, 10 - centerH, { origin: inner })
44-
.pointerDown()
45-
// Move pointer to the center of the button.
46-
.pointerMove(0, 0, { origin: inner })
47-
.pointerUp()
48-
.send();
49-
}).then(didReceiveDragStart => {
50-
assert_false(didReceiveDragStart, "dragstart should not fire");
51-
});
52-
}, "Button inside draggable element should not be draggable from border");
26+
function testDragButton(dragActionFun, msg) {
27+
promise_test(t => {
28+
return new Promise((resolve, reject) => {
29+
let result = {};
30+
31+
const dragStartListener = ev => {
32+
ev.preventDefault();
33+
result.didReceiveDragStart = true;
34+
result.targetId = ev.target.id;
35+
result.dataTransferItemsCount = ev.dataTransfer.items.length;
36+
result.dataTransferTypesCount = ev.dataTransfer.types.length;
37+
};
38+
outer.addEventListener("dragstart", dragStartListener, { once: true });
39+
t.add_cleanup(() => outer.removeEventListener("dragstart", dragStartListener));
40+
41+
outer.addEventListener("mouseup", () => {
42+
resolve(result);
43+
}, { once: true });
44+
45+
dragActionFun();
46+
}).then(result => {
47+
assert_true(result.didReceiveDragStart, "dragstart should not fire");
48+
assert_equals(result.targetId, "outer", "should drag outer element");
49+
assert_equals(result.dataTransferItemsCount, 0, "dataTransfer should have no items");
50+
assert_equals(result.dataTransferTypesCount, 0, "dataTransfer should have no types");
51+
});
52+
}, msg);
53+
}
54+
55+
testDragButton(async () => {
56+
const centerH = inner.getBoundingClientRect().height / 2;
57+
new test_driver.Actions()
58+
// Move pointer to the center of the top-border.
59+
.pointerMove(0, 10 - centerH, { origin: inner })
60+
.pointerDown()
61+
// Move pointer to the center of the button.
62+
.pointerMove(0, 0, { origin: inner })
63+
.pointerUp()
64+
.send();
65+
}, "Draggable button should be draggable from border");
66+
67+
testDragButton(async () => {
68+
const centerW = inner.getBoundingClientRect().width / 2;
69+
new test_driver.Actions()
70+
// Move pointer to the start of the button text.
71+
.pointerMove(5 - centerW, 10, { origin: inner })
72+
.pointerDown()
73+
// Move pointer rightward.
74+
.pointerMove(0, 10, { origin: inner })
75+
.pointerUp()
76+
.send();
77+
}, "Draggable button should be draggable from button text");
5378
</script>
5479

5580
</body>

html/editing/dnd/interactiveelements/draggable_button.html

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,68 @@
1313
</head>
1414
<body>
1515

16-
<p>Press your mouse button down on the orange block and drag downwards. It should <strong>not</strong> drag the block or text.</p>
17-
<div id="element">
16+
<p>Press your mouse button down on the orange block and drag downwards. It should drag the button.</p>
17+
<p>Press your mouse button down on the text and drag rightward. It should drag the button.</p>
18+
<div id="outer">
1819
<button draggable="true" id="inner">Dummy text</button>
1920
</div>
2021

2122
<script>
22-
const element = document.getElementById("element");
23+
const outer = document.getElementById("outer");
2324
const inner = document.getElementById("inner");
2425

25-
promise_test(function(t) {
26-
return new Promise((resolve, reject) => {
27-
let didReceiveDragStart = false;
28-
29-
const dragStartListener = ev => {
30-
ev.preventDefault();
31-
didReceiveDragStart = true;
32-
};
33-
element.addEventListener("dragstart", dragStartListener, { once: true });
34-
t.add_cleanup(() => element.removeEventListener("dragstart", dragStartListener));
35-
36-
element.addEventListener("mouseup", () => {
37-
resolve(didReceiveDragStart);
38-
}, { once: true });
39-
40-
const centerH = inner.getBoundingClientRect().height / 2;
41-
new test_driver.Actions()
42-
// Move pointer to the center of the top-border.
43-
.pointerMove(0, 10 - centerH, { origin: inner })
44-
.pointerDown()
45-
// Move pointer to the center of the button.
46-
.pointerMove(0, 0, { origin: inner })
47-
.pointerUp()
48-
.send();
49-
}).then(didReceiveDragStart => {
50-
assert_false(didReceiveDragStart, "dragstart should not fire");
51-
});
52-
}, "Draggable button should not be draggable from border");
26+
function testDragButton(dragActionFun, msg) {
27+
promise_test(t => {
28+
return new Promise((resolve, reject) => {
29+
let result = {};
30+
31+
const dragStartListener = ev => {
32+
ev.preventDefault();
33+
result.didReceiveDragStart = true;
34+
result.targetId = ev.target.id;
35+
result.dataTransferItemsCount = ev.dataTransfer.items.length;
36+
result.dataTransferTypesCount = ev.dataTransfer.types.length;
37+
};
38+
outer.addEventListener("dragstart", dragStartListener, { once: true });
39+
t.add_cleanup(() => outer.removeEventListener("dragstart", dragStartListener));
40+
41+
outer.addEventListener("mouseup", () => {
42+
resolve(result);
43+
}, { once: true });
44+
45+
dragActionFun();
46+
}).then(result => {
47+
assert_true(result.didReceiveDragStart, "dragstart should not fire");
48+
assert_equals(result.targetId, "inner", "should drag inner element");
49+
assert_equals(result.dataTransferItemsCount, 0, "dataTransfer should have no items");
50+
assert_equals(result.dataTransferTypesCount, 0, "dataTransfer should have no types");
51+
});
52+
}, msg);
53+
}
54+
55+
testDragButton(async () => {
56+
const centerH = inner.getBoundingClientRect().height / 2;
57+
new test_driver.Actions()
58+
// Move pointer to the center of the top-border.
59+
.pointerMove(0, 10 - centerH, { origin: inner })
60+
.pointerDown()
61+
// Move pointer to the center of the button.
62+
.pointerMove(0, 0, { origin: inner })
63+
.pointerUp()
64+
.send();
65+
}, "Button inside draggable element should be draggable from border");
66+
67+
testDragButton(async () => {
68+
const centerW = inner.getBoundingClientRect().width / 2;
69+
new test_driver.Actions()
70+
// Move pointer to the start of the button text.
71+
.pointerMove(5 - centerW, 10, { origin: inner })
72+
.pointerDown()
73+
// Move pointer rightward.
74+
.pointerMove(0, 10, { origin: inner })
75+
.pointerUp()
76+
.send();
77+
}, "Button inside draggable element should be draggable from button text");
5378
</script>
5479

5580
</body>

html/editing/dnd/interactiveelements/draggable_input_button.html

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,68 @@
1313
</head>
1414
<body>
1515

16-
<p>Press your mouse button down on the orange block and drag downwards. It should <strong>not</strong> drag the block or text.</p>
17-
<div id="element">
16+
<p>Press your mouse button down on the orange block and drag downwards. It should drag the input button.</p>
17+
<p>Press your mouse button down on the text and drag rightward. It should drag the input button.</p>
18+
<div id="outer">
1819
<input type="button" value="Dummy text" draggable="true" id="inner">
1920
</div>
2021

2122
<script>
22-
const element = document.getElementById("element");
23+
const outer = document.getElementById("outer");
2324
const inner = document.getElementById("inner");
2425

25-
promise_test(t => {
26-
return new Promise((resolve, reject) => {
27-
let didReceiveDragStart = false;
28-
29-
const dragStartListener = ev => {
30-
ev.preventDefault();
31-
didReceiveDragStart = true;
32-
};
33-
element.addEventListener("dragstart", dragStartListener, { once: true });
34-
t.add_cleanup(() => element.removeEventListener("dragstart", dragStartListener));
35-
36-
element.addEventListener("mouseup", () => {
37-
resolve(didReceiveDragStart);
38-
}, { once: true });
39-
40-
const centerH = inner.getBoundingClientRect().height / 2;
41-
new test_driver.Actions()
42-
// Move pointer to the center of the top-border.
43-
.pointerMove(0, 10 - centerH, { origin: inner })
44-
.pointerDown()
45-
// Move pointer to the center of the button.
46-
.pointerMove(0, 0, { origin: inner })
47-
.pointerUp()
48-
.send();
49-
}).then(didReceiveDragStart => {
50-
assert_false(didReceiveDragStart, "dragstart should not fire");
51-
});
52-
}, "Draggable input button should not be draggable from border");
26+
function testDragInputButton(dragActionFun, msg) {
27+
promise_test(t => {
28+
return new Promise((resolve, reject) => {
29+
let result = {};
30+
31+
const dragStartListener = ev => {
32+
ev.preventDefault();
33+
result.didReceiveDragStart = true;
34+
result.targetId = ev.target.id;
35+
result.dataTransferItemsCount = ev.dataTransfer.items.length;
36+
result.dataTransferTypesCount = ev.dataTransfer.types.length;
37+
};
38+
outer.addEventListener("dragstart", dragStartListener, { once: true });
39+
t.add_cleanup(() => outer.removeEventListener("dragstart", dragStartListener));
40+
41+
outer.addEventListener("mouseup", () => {
42+
resolve(result);
43+
}, { once: true });
44+
45+
dragActionFun();
46+
}).then(result => {
47+
assert_true(result.didReceiveDragStart, "dragstart should not fire");
48+
assert_equals(result.targetId, "inner", "should drag inner element");
49+
assert_equals(result.dataTransferItemsCount, 0, "dataTransfer should have no items");
50+
assert_equals(result.dataTransferTypesCount, 0, "dataTransfer should have no types");
51+
});
52+
}, msg);
53+
}
54+
55+
testDragInputButton(async () => {
56+
const centerH = inner.getBoundingClientRect().height / 2;
57+
new test_driver.Actions()
58+
// Move pointer to the center of the top-border.
59+
.pointerMove(0, 10 - centerH, { origin: inner })
60+
.pointerDown()
61+
// Move pointer to the center of the input button.
62+
.pointerMove(0, 0, { origin: inner })
63+
.pointerUp()
64+
.send();
65+
}, "Draggable input button should be draggable from border");
66+
67+
testDragInputButton(async () => {
68+
const centerW = inner.getBoundingClientRect().width / 2;
69+
new test_driver.Actions()
70+
// Move pointer to the start of the input button text.
71+
.pointerMove(5 - centerW, 10, { origin: inner })
72+
.pointerDown()
73+
// Move pointer rightward.
74+
.pointerMove(0, 10, { origin: inner })
75+
.pointerUp()
76+
.send();
77+
}, "Draggable input button should be draggable from button text");
5378
</script>
5479

5580
</body>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>Draggable input image</title>
5+
<script src="/resources/testharness.js"></script>
6+
<script src="/resources/testharnessreport.js"></script>
7+
<script src="/resources/testdriver.js"></script>
8+
<script src="/resources/testdriver-vendor.js"></script>
9+
<script src="/resources/testdriver-actions.js"></script>
10+
<style type="text/css">
11+
#inner { border: 1px solid orange; border-top-width: 20px; }
12+
</style>
13+
</head>
14+
<body>
15+
16+
<p>Press your mouse button down on the orange block and drag downwards. It should drag the input image.</p>
17+
<p>Press your mouse button down on the image and drag downwards. It should drag the input image.</p>
18+
<div id="outer">
19+
<input type="image" src="../resources/circle.png" value="Dummy text" draggable="true" id="inner">
20+
</div>
21+
22+
<script>
23+
const outer = document.getElementById("outer");
24+
const inner = document.getElementById("inner");
25+
26+
function testDragInputImageButton(dragActionFun, msg) {
27+
promise_test(t => {
28+
return new Promise((resolve, reject) => {
29+
let result = {};
30+
31+
const dragStartListener = ev => {
32+
ev.preventDefault();
33+
result.didReceiveDragStart = true;
34+
result.targetId = ev.target.id;
35+
result.dataTransferItemsCount = ev.dataTransfer.items.length;
36+
result.dataTransferTypesCount = ev.dataTransfer.types.length;
37+
};
38+
outer.addEventListener("dragstart", dragStartListener, { once: true });
39+
t.add_cleanup(() => outer.removeEventListener("dragstart", dragStartListener));
40+
41+
outer.addEventListener("mouseup", () => {
42+
resolve(result);
43+
}, { once: true });
44+
45+
dragActionFun();
46+
}).then(result => {
47+
assert_true(result.didReceiveDragStart, "dragstart should not fire");
48+
assert_equals(result.targetId, "inner", "should drag inner element");
49+
assert_equals(result.dataTransferItemsCount, 0, "dataTransfer should have no items");
50+
assert_equals(result.dataTransferTypesCount, 0, "dataTransfer should have no types");
51+
});
52+
}, msg);
53+
}
54+
55+
promise_test(async t => {
56+
await new EventWatcher(t, window, "load").wait_for("load");
57+
}, "Wait for image load");
58+
59+
testDragInputImageButton(async () => {
60+
const centerH = inner.getBoundingClientRect().height / 2;
61+
new test_driver.Actions()
62+
// Move pointer to the center of the top-border.
63+
.pointerMove(0, 10 - centerH, { origin: inner })
64+
.pointerDown()
65+
// Move pointer to the center of the button.
66+
.pointerMove(0, 0, { origin: inner })
67+
.pointerUp()
68+
.send();
69+
}, "Draggable input image button should be draggable from border");
70+
71+
testDragInputImageButton(async () => {
72+
new test_driver.Actions()
73+
// Move pointer to the center of the image.
74+
.pointerMove(0, 10, { origin: inner })
75+
.pointerDown()
76+
// Move pointer downwards.
77+
.pointerMove(0, 30, { origin: inner })
78+
.pointerUp()
79+
.send();
80+
}, "Draggable input image button should be draggable from image");
81+
</script>
82+
83+
</body>
84+
</html>

0 commit comments

Comments
 (0)