schne324 / dragon-drop Goto Github PK
View Code? Open in Web Editor NEWAccessible drag and drop list reorder module
Home Page: https://schne324.github.io/dragon-drop/demo/
License: MIT License
Accessible drag and drop list reorder module
Home Page: https://schne324.github.io/dragon-drop/demo/
License: MIT License
Description
When I click on the drag handle, it puts that element in a state of aria-pressed="true" data-drag-on="true"
. I only want those things to happen when the element is truly being dragged.
Steps to Repro:
Expected Result
State described above is only applied in a true "grab" (when I click+drag or when I hit the space/enter key).
Actual Result
State is applied on click of the item and cannot be removed, unless the user selects a different item from the list with the mouse or keyboard.
Additional Info
I had an idea for fixing this:
onKeyDown
method - const event = new Event('grab');
target.click()
--> target.dispatchEvent(event)
initClick()
set each handle to listen for the new event handle.addEventListener('grab', ...)
document.addEventListener('click', ...)
to remove any of the "grabbed" state attributes, if the user clicks anywhere else in the document.#4 is maybe not the best solution, but an idea. Let me know what you think of the above.
After initialisation, new items added to the container can be moved with the mouse, but not the keyboard.
For an example, go to https://schne324.github.io/dragon-drop/demo/ and add a new item to the first demo by running this in the console:
$('#demo-1').appendChild($('#demo-1').lastElementChild.cloneNode(true))
Tabbing onto the new handle and pressing return does nothing, however dragging it with the mouse works.
Hi,
There's an XSS vulnerability while rendering the LiveRegion when the list is generated with user input. I also managed to recreate it in the demo.
Steps to recreate:
Ween
with "><img src=x onerror="alert('Evil script');" />
. (Make sure that the text in the dom is encoded, so "><img src=x onerror="alert('Evil script');" />
.)The problem lies with the use of HTMLElement.innerText
for the default announcements.
announcement: {
grabbed: function grabbed(el) {
return 'Item ' + el.innerText + ' grabbed';
},
dropped: function dropped(el) {
return 'Item ' + el.innerText + ' dropped';
},
reorder: function reorder(el, items) {
var pos = items.indexOf(el) + 1;
var text = el.innerText;
return 'The list has been reordered, ' + text + ' is now item ' + pos + ' of ' + items.length;
},
cancel: 'Reordering cancelled'
}
Some documentation on XSS prevention can be found here https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html.
Hi. Thanks for working through this problem so the rest of us don't have to.
I'm interested in using the library but testing it on my iPhone 8 Plus in Chrome on iOS 13.1.2 (latest OS as of this writing), I noticed it's not working as neatly as the desktop version: it seems that pressing and holding on the draggable DIVs in the list does not actually take until the browser goes into its text-select mode (meaning the mode you enter to select some text in a paragraph, for example). You can see the iOS blue text-select highlight box while you drag in some cases, (which could be dealt with with user-select: none; as a style possibly), but most importantly, there is a delay in between touching the div and it actually allowing you to drag, so if you touch and drag immediately, you scroll the page.
Is this intended as a mobile solution as well or am I barking up the wrong tree here?
Thanks very much.
My project uses drag-and-drop interfaces that are not currently accessible, and I'd love to use dragon drop to replace our current sorting jquery plugin. Many of our interfaces are for creating navigation lists, and so the ability to nest the sortable items is key.
We had some accessibility problems with this, reproducible on the demo page: I tried the "rank the bands" thing with NVDA running, but because it uses an OL to group the elements, the screen reader is in browse mode, which means it 'eats' the arrow keystrokes. (OL is not an operable element type).
Lots of accessibility jargon there, you might need guidance, so there is some background on screen reader interaction modes here.
So it means that if you have NVDA running, you can grab and drop the items, but not actually move them. Other screen readers and assistive tech (notably JAWS) will have the same problem.
Possible Solution: Add role=application
to the OL, and 'it just works' because it puts the assistive tech into 'forms mode' (also known as 'application mode'). Other operable roles might be more appropriate in a given case. Screen reader announcements are a bit chatty but communicate the right info otherwise.
I am not sure if this is the perfect solution, because it depends on the semantic context where this gadget will end up, but it's relatively easy to do and certainly makes dragon-drop work with NVDA, probably JAWS too. Accessible drag-and-drop is quite tricky, so that's a win, I should think!
Hello again,
I was wondering if you have any recommendations for unit testing the dragon-drop functionality in an Angular app. I've set up my code according to the documentation:
import DragonDrop from 'drag-on-drop';
// Other component stuff goes here
this.keyboardDragon = new DragonDrop(this.dragon.nativeElement, {
item: 'mapping-item-source-dest-position',
handle: false,
activeClass: 'gu-mirror-keyboard'
});
this.keyboardDragon.on('dropped', (_, item) => {
// Do some stuff
});
But when I run my jasmine tests, I get the following error:
TypeError: drag_on_drop_1.default is not a constructor
Any ideas?
https://bundlephobia.com/[email protected]
react framework has lower size
why it's matters
https://addyosmani.com/blog/performance-budgets/
Thanks for this lib!
Actual: page is scrolled
Expected: page remains fixed, only item moves
Adding overflow-y: hidden
while dragging to <body>
will fix this, but stopping event bubbling might be a better fix.
Hi,
In both my own code and on the demo page at https://schne324.github.io/dragon-drop/demo/ none of the callback functions are executed. Given this basic example:
dragonDrop
.on('grabbed', (container, item) => console.log(`Item ${item.innerText} grabbed`))
.on('dropped', (container, item) => console.log(`Item ${item.innerText} dropped`))
.on('reorder', (container, item) => console.log(`Reorder: ${item.innerText} has moved`))
.on('cancel', () => console.log('Reordering cancelled'));
None of these log events appear in the console. And this is true for me even on the demo page at https://schne324.github.io/dragon-drop/demo/ .
Further, on the demo page the reorder
announcement is never displayed, only grabbed
and dropped
. Browser breakpoints do fire for grabbed
and dropped
; no breakpoint fires for reorder
(in Chrome, Firefox, Edge). If I add localStorage.debug = 'drag-on-drop:*';
I can see console logs for grabbed
and dropped
, but again, not for reorder
.
Normally I'd be happy to admit that my code is wrong, but I can't see it working on the demo page either :(.
Thanks,
Hello,
I have this issue where the mirrored (moving) div is appended in the body. In dragula, we have the option of passing a scope with the attribute mirrorContainer: yourcontainer
.
dragula([this.reorderableList], { mirrorContainer: this.reorderableList });
Is it possible to have this option accessible from the Drag on Drop interface ? I can't manage to make it work without it...
Thank you !
This will require some decent refactor (ATM the only nested support locks sublist items into the list the are initially in)
We want to use handles and use them with nested lists. It seems when you are nested, it only supports that you move the whole li and it does not use handles. Is there a way to have handle buttons on sub items or is that only supported with 1 level?
Is it intended that for draggables that have handles, that you are still able to drag the item without having to start the drag on the item's handle?
I'm working on an project that uses Angular 6 and would like to use this library for the keyboard interactions, and the Angular 2 bridge for dragula for the mouse interactions (ie. ng2-dragula
).
In my project, I have a list of items that are sorted by a position
property. When you re-order the items on the list, via dragging an item with the mouse or keyboard, the position
property for all the items in the array is updated.
ng2-dragula
has a new event available in the service called dropModel
; an observable that sends over a few properties, most notably the targetModel
, so I can easily update the positions of each item in the array. This takes care of the above paragraph for mouse interactions.
However, I'm struggling a bit when using this library to figure out how to do this for the keyboard interactions. I have some ideas for features that could make this easier:
.on('dropped')
callback function, so that there's some way to determine new positions with the dropped item.ng2-dragula
. As it stands now, I think I'm creating two - one with your lib, and one with ng2-dragula
. Not sure this would solve my problem with the keyboard events though.Please let me know if there is something I'm missing or any other ideas you may have.
I have the need to add delete buttons on each sublist element, but I cannot seem to delegate a click event on my buttons because the event is always handled by DragonDrop. The list items and delete buttons are being added dynamically. Any suggestions?
Would be great to get feedback on:
https://www.drupal.org/project/drupal/issues/2920006#comment-12322128
I have created a drag and drop project whose basis is to allow items from container 1 to be draggable to container 2 and vice versa, as well as allowing items to be reordered within their containers. For the first iteration of my project I have achieved this using dragula.
However, I need to make this accessible and was looking at using dragon-drop, however I don't think it is currently possible to implement dragon-drop in this way, is that correct?
I have a list of items that I need to update on the server when a reorder is performed. To do this I hook into the dropped
event and perform an ajax call . However, it appears that the dropped
event fires even when a user cancels the re-order with esc
. Is this intended functionality?
It'd be nice to support fancy animation for the keyboard experience. Explore what it'll take to support this but it needs to be configurable (so its easy for implementers to turn animation on/off)
Description:
I was having an issue opening my project in IE, so I wanted to make sure the demo was working in IE 11. Doesn't look like I'm able to do many of the interactions, with the keyboard or the mouse.
Steps to Repro:
Expected Result:
Item moves up/down, as seen in Chrome
Actual Result:
Handle is in focus, but not selected. Arrow keys scroll browser window.
The docs say to use dragonDrop.dragula.on('drop', ...);
for mouse events, but no matter what I do I can't seem to actually access dragula. Using the 'nested lists' example from the demo, I've tried:
DragonDrop.dragula.on('drop', ...)
dragons.dragula.on('drop', ...)
dragon.dragula.on('drop', ...)
(within dragons.forEach
)Each of those seems to throw Uncaught TypeError: Cannot read property 'on' of undefined
. Any thoughts?
I have an issue with adding new list entries after DragonDrop was applied to a list.
In my case I have a list containing a few items and apply DragonDrop to this list. Everything works here as expected.
At some point I want to add a new list entry to this list dynamically. After adding this entry (by using the jQuery.append() function) the reordering using the mouse works fine but selecting the new entry is not possible and thus the reordering using the keyboard also does not work.
I would consider this as an issue or is there any way to "refresh" DragonDrop or completely "destroy" DragonDrop on this list and reapply it once the new list item is added?
I've prepared a little example here. There is a button below the list which adds a new list entry dynamically. After the new entry is added you can't reorder it by using the keyboard.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.