Skip to content

Commit b3f5077

Browse files
committed
fix(pat-sortable): Initialize already existing sortable handles.
Also allow the sortable itself to be the handle.
1 parent df318af commit b3f5077

File tree

3 files changed

+83
-33
lines changed

3 files changed

+83
-33
lines changed

src/pat/sortable/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ <h2>Vertical sorting with pat-clone</h2>
3939
</template>
4040

4141

42+
<h2>The sortable item can also be the sortable handle</h2>
43+
<ul class="pat-sortable">
44+
<li class="sortable-item sortable-handle" draggable="true">Item 3</li>
45+
<li class="sortable-item sortable-handle" draggable="true">Item 5</li>
46+
<li class="sortable-item sortable-handle" draggable="true">Item 4</li>
47+
<li class="sortable-item sortable-handle" draggable="true">Item 1</li>
48+
<li class="sortable-item sortable-handle" draggable="true">Item 6</li>
49+
<li class="sortable-item sortable-handle" draggable="true">Item 2</li>
50+
</ul>
51+
52+
4253
<style>
4354
.sortable-item {
4455
margin-bottom: -3px;

src/pat/sortable/sortable.js

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import $ from "jquery";
22
import Base from "../../core/base";
3+
import dom from "../../core/dom";
34
import events from "../../core/events";
45
import Parser from "../../core/parser";
56

@@ -50,36 +51,44 @@ export default Base.extend({
5051
},
5152

5253
addHandles: function () {
53-
for (const sortable of [...this.$sortables].filter(
54-
(it) => !it.querySelector(".sortable-handle")
55-
)) {
56-
// TODO: we should change to a <button>.
57-
const handle = document.createElement("a");
58-
handle.textContent = "⇕";
59-
handle.classList.add("sortable-handle");
60-
handle.setAttribute("draggable", "true");
61-
handle.setAttribute("href", "#");
62-
handle.setAttribute("title", "Drag to reorder");
63-
handle.setAttribute("aria-label", "Drag to reorder");
64-
sortable.appendChild(handle);
65-
66-
// TODO: remove when element is a button.
67-
events.add_event_listener(handle, "click", "pat-sortable--click", (e) => {
68-
e.preventDefault();
69-
});
70-
71-
events.add_event_listener(
72-
handle,
73-
"dragstart",
74-
"pat-sortable--dragstart",
75-
this.onDragStart.bind(this)
76-
);
77-
events.add_event_listener(
78-
handle,
79-
"dragend",
80-
"pat-sortable--dragend",
81-
this.onDragEnd.bind(this)
82-
);
54+
for (const sortable of this.$sortables) {
55+
const handles = dom.querySelectorAllAndMe(sortable, ".sortable-handle");
56+
if (handles.length === 0) {
57+
// TODO: we should change to a <button>.
58+
const handle = document.createElement("a");
59+
handle.textContent = "⇕";
60+
handle.classList.add("sortable-handle");
61+
handle.setAttribute("draggable", "true");
62+
handle.setAttribute("href", "#");
63+
//handle.setAttribute("title", "Drag to reorder"); // TODO: specify if that should be kept.
64+
handle.setAttribute("aria-label", "Drag to reorder");
65+
sortable.appendChild(handle);
66+
handles.push(handle);
67+
}
68+
69+
for (const handle of handles) {
70+
// TODO: remove when element is a button.
71+
events.add_event_listener(
72+
handle,
73+
"click",
74+
"pat-sortable--click",
75+
(e) => {
76+
e.preventDefault();
77+
}
78+
);
79+
events.add_event_listener(
80+
handle,
81+
"dragstart",
82+
"pat-sortable--dragstart",
83+
this.onDragStart.bind(this)
84+
);
85+
events.add_event_listener(
86+
handle,
87+
"dragend",
88+
"pat-sortable--dragend",
89+
this.onDragEnd.bind(this)
90+
);
91+
}
8392
}
8493
},
8594

@@ -111,7 +120,7 @@ export default Base.extend({
111120
},
112121

113122
onDragEnd: function (ev) {
114-
var $dragged = $(ev.target).parent();
123+
const $dragged = $(ev.target.closest(this.options.selector));
115124
$dragged.removeClass(this.options.dragClass);
116125
this.$sortables.off(".pat-sortable");
117126
this.$el.off(".pat-sortable");
@@ -156,8 +165,7 @@ export default Base.extend({
156165
},
157166

158167
onDragStart: function (ev) {
159-
var $handle = $(ev.target);
160-
var $dragged = $handle.parent();
168+
const $dragged = $(ev.target.closest(this.options.selector));
161169
var that = this;
162170
if (ev.dataTransfer) {
163171
// Firefox seems to need this set to any value

src/pat/sortable/sortable.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,35 @@ describe("pat-sortable", function () {
213213

214214
expect(injected.classList.contains(sortable.options.dragClass)).toBe(true);
215215
});
216+
217+
it("7 - Initializes sorting behavior with existing handles.", function () {
218+
document.body.innerHTML = `
219+
<ul class="pat-sortable">
220+
<li>item 1 <a class="sortable-handle">sort</a></li>
221+
</ul>
222+
`;
223+
const el = document.querySelector(".pat-sortable");
224+
const sortable = new Sortable(el);
225+
226+
const item = el.querySelector("li");
227+
const drag_handle = item.querySelector(".sortable-handle");
228+
drag_handle.dispatchEvent(new Event("dragstart"));
229+
230+
expect(item.classList.contains(sortable.options.dragClass)).toBe(true);
231+
});
232+
233+
it("8 - Sortable item itself can be the handle.", function () {
234+
document.body.innerHTML = `
235+
<ul class="pat-sortable">
236+
<li class="sortable-handle">item</li>
237+
</ul>
238+
`;
239+
const el = document.querySelector(".pat-sortable");
240+
const sortable = new Sortable(el);
241+
242+
const item = el.querySelector("li");
243+
item.dispatchEvent(new Event("dragstart"));
244+
245+
expect(item.classList.contains(sortable.options.dragClass)).toBe(true);
246+
});
216247
});

0 commit comments

Comments
 (0)