The HTML5 drag and drop disaster (2009)
quirksmode.org
quirksmode.org
There are two places likely to trip you up. One of them is as mentioned in the original article: it's hard to remember which events need to have their default prevented. At the moment we're calling `preventDefault` in `onDragOver` which is required to identify the element as a drop target, and `stopPropagation` in `onDrop` which I believe is to prevent many browsers' default attempts to navigate to a dropped url-like thing.
The other potential pitfall is that, for security reasons, the data can only be read in `onDrop`, not in `onDragOver`. If you have a string id you don't mind being downcased you can just use the hack of sending that through the data transfer types (eg. as type "id/12345"), with a "text/plain" fallback.
> This seems rather a lot for a series of actions that can be accurately described by the mousedown, mousemove, and mouseup events.
Mouse events also include mouseover, mouseout, mouseenter, and mouseleave.
The start/over/enter/leave events serve useful purposes, notably that you can offer UI cues to the user. For instance, if you drag an image onto an image search page that normally accepts text, the search box can become a giant drop target with "drop image here to search" text. And if you drag a non-image onto the same page, the page can check the MIME type and give the user UI that says that won't work.
Read the rest of the article: there's a lot of other stupid API shit that heavily outweighs any clever little benefits.
Not to mention onclick and ondblclick, which really needs access to the OS-level double-click delay setting if you want it to behave properly.
<dragarea group="groupX">
<draggable value="abc">
whatever you want here
</draggable>
</dragarea>
<dragarea group="groupX" name="variableName">
</dragarea>
You drag element from first dragarea and get variableName=abc on the server. Multiple values work same was as checkboxes.Fancy events could be added incrementally, later.
If I could not use a library, I would look for the unminified code of a library and copy and paste it the relevant section.
Because ultimately, unless things go wrong and I need to dig deep, I have better things to do than mastering yet another complex web api.
That being said; it seems like a copout to ignore glaring issues while waving our collective hands in the air and saying "just use a library to abstract it!"
One of the reasons libraries are as popular as they are (particularly JQuery which does "nothing" except provide an abstraction) is because the standards are so weak and cross browser support so incomplete.
A lot of people think we're currently in a great place in terms of web-development. I actually disagree. We're still in a bad place, it just so happens that were were in an even worse place previously (e.g. IE6 era).
Is there any real motive in the standardisation community or web community in general to make the spec' good enough so JQuery is no longer required by 9/10 websites? Why isn't $('#something').click(); built in yet?
document.getElementById('something').addEventListener('click',function() {})
works on all browsers these days. But we're stuck in our habits.I don't deny that web development is kind of crappy, but it's just in the nature of it - the reason why iOS and Android are easier to develop for is because there's really only one client for them. Personally, I'll take the multiple, open client approach over the closed one any day, warts and all.
There is documentation as well in here : http://ganarajpr.github.io/angular-dragdrop/
Having read the blog ( from top to end ) I kind of agree with some of the things that the author says. There are a few edge cases that we need to take care of if using native drag and drop. There is also the not-so-slight issue that it doesnt work on mobile browsers....
Or maybe you have multiple drop areas stacked on each other. Should the event propagate to the parent element or not?
Ok, why is it done in JavaScript and not simply with dropzone="true"? Because you want to be able to let script logic decide if that drop/dragover event is eaten or not.
I stopped reading at some point, but I wonder if the author has ever implemented D'n'D support in any other language. It works very similar to this in I guess most GUI APIs. Maybe that is another reason why it works like that in HTML5?
Arguably, you should be able to implement just the 'drop' event and call event.preventDefault() in that event to suppress the default behavior of loading the file/URL. I don't see a clear reason why any other event should matter, the actual action that triggers the load is dropping.
As for propagation to parent elements, that's not controlled by event.preventDefault(), that's controlled by event.stopPropagation().
I do agree that the author doesn't seem to realize that drag & drop is actually rather complex and that other languages look similar (e.g. large number of events). But the quirks around when you have to call preventDefault() do seem to be legitimate issues.
As to "I don't see a clear reason why any other event should matter". Well, yeah, one could implement it so that only the drop event really matters, but I guess it's done the way it is so it forces the programmer to explicitly handle the dragover event. This way the appropriate mouse icon will be displayed and the user knows what's going to happen when they drop now.
Strange situation where I, a Linux user, defend something made by Microsoft. Usually I spew a lot of hate against Microsoft just for committing the crime called Internet Explorer (especially version 8, which I still have to support, bah).
The specs for DnD are written very well but the implementation is brilliantly fucked up that the only way you are left is to use a library and enjoy the hardwork of someone who spent hours getting smeared in the dirt.
As far as I remember if you do that (i.e. if you use mousedown, mouseover, etc and move your dragged element accordingly), the result won't be nearly as good as with "native" drag and drop, and you will see the dragged element lagging behind the cursor.
http://www.html5rocks.com/en/tutorials/dnd/basics/
I don't understand why this is an issue, there are tons of great tutorials: https://www.google.com/search?q=HTML5+drag-and-drop
Step 1 to being a web developer, search Google first. More than likely anything you need done has been done 10,000 times and there are at least 100 tutorials.
Don't be afraid to use libraries such as jQuery,which HTML5 drag-and-drop doesn't require, but I see that you mentioned avoiding it in another comment. Libraries many times also have the advantage of increasing browser support transparently, which is generally a good thing.
Worried about loading time with libraries? Use a CDN such as http://cdnjs.com/, most users will have the popular ones already cached in their browser.
Use StackOverflow if you have questions, that's what it's there for. Hacker News is for... news.
> Don't be afraid to use libraries such as jQuery, ...
So, bad specs are not an issue because there are tutorials explaining how to use them and there are slightly better abstractions on top of them?
* I prefer to avoid libraries when possible, especially when diametrically opposed ones are in use (I'm making an Angular app, JQuery doesn't always play nice).
* Thank you for the tip about http://cdnjs.com/, I'll be using it in the future.
* Hacker News is news, but it's also about discussion. That and I've personally never heard of how bad HTML5 DnD was, I thought the community might benefit from looking into it too.
I guess if you're trying direct dom manipulation on the same elements from outside of Angular with JQuery and with Angular it could get messy. The community would just say "you're not doing it the Angular way." You're not. You can use the JQuery inside a directive and controller and be fine.
Edit: see comment above as well about JQuery plugins.
We use drag and drop for sorting in a few places. Our initial implementation was to wrap jQuery UI Sortable in a directive. This worked to an extent, but for our purpose, we ended up having to read the DOM and update the Angular scope from the DOM after jqUI emitted its event. This logic ended up being somewhat clunky.
We rewrote our directive in terms of HTML5 drag and drop such that when a user drops something, we get an event on the Angular scope, saying which element was dragged, and which element it was dropped on and then our controller rearranges the array in the scope, and only then is the DOM modified by Angular.
This generally isn't possible with jqUI and its plugins, which modify the DOM first and tell you about it later (in such unhelpful low level terms as "moved 100px up" rather than "moved two elements forward").
If you want simple, you're going to have to use a library, what you're basically asking for is for the HTML5 spec to emulate jQuery and cut out the options that you specifically don't need, which isn't reasonable.
http://www.html5tuts.co.uk/demos/drag/
Here is a very cool dragging demo using jQuery: http://threedubmedia.com/demo/drag/
If you have a solution to the HTML5 spec to simplify it then please write an article and we'll support it if it's reasonable and do our best to get it added to the spec (it won't be implemented into browsers for a few years though). Remember you have to support lots of use-cases, touchscreens, old browser support (unfortunate reality).
The only real complaint in the original linked-to article is about having too many events (they're not all required to be used), then it says that you have to add some CSS for it to work properly in Safari (sounds like Safari's problem, not the HTML5 spec's fault).
So, one would say "singletons considered harmful". The entire notion of singletons is wrong. But the entire notion of drag/drop events is not wrong. Just the implementation.
[1] It's interesting to read some of the counter-arguments, and reflect on programming language design arguments we have today: http://web.archive.org/web/20090320002214/http://www.ecn.pur..., and Dijkstra's own commentary on the whole ordeal is--as usual--entertaining http://www.cs.utexas.edu/users/EWD/ewd10xx/EWD1009.PDF
Edit: Ah, yes, Eric Meyer [1], complaining about "...considered harmful" seven years prior to the original article. :-)
Excellent point. What is it about us techies that we have to always be right, and demonstrate it in the most indignant way, damn the consequences?
Could you expand on that? Haven't heard this argument before
This has all kinds of nasty downstream effects. It becomes more difficult to trace the dependencies between classes, since any class can invisibly depend on a singleton. It becomes painful/impossible to replace that dependency in a particular instance, which makes both testing and extension difficult.
Dependency injection solves the issue of sharing copies of the same object, without forcing that the object is implemented as a singleton. You can inject a different/extended implementation, and it becomes easy to trace dependencies.
Sometimes you just really need some global state. Have you ever done game development? Unless you want to pass a giant GameState godobject to every single thing. Singletons or static classes: NotificationManager.PushNotification(..), DBManager.Instance.UpdatePosition(..)
Singletons are good for when you want a static class but also need some things you can only do with instance classes.
Static classes are a hack for languages that force everything to be an object. You don't see static classes in languages like C++ or Common Lisp or JavaScript. You pretty much only see it in Java or C#. You make global (though certainly namespaced, we don't need to be colliding names here) functions instead.
And the difference between instance classes and static classes is that instance classes encapsulate state. So a singleton is literally nothing more than stateful global functions.
The realization you're starting to need a GameState godobject is what is called a code-smell, i.e. trying to find answers to the wrong problem of "how do we get all of this state around?" The problem should more correctly be "how do we avoid needing to have so much state passed around?"
It's usually a sign that the project is using too much inheritance. It seems natural to have a class "ProjectileWeapon" that has a virtual "fire()" method that returns a "Projectile", from which "Gun" inherits and overrides fire() to return a "Bullet" and "RocketLauncher" overrides to return "Rocket". But the Bullet only has a momentum vector, the Rocket also has fuel, and the Bullet only does kinetic damage, the Rocket includes chemical, and different materials are more or less resistant to different types of damage. The interactions between types that all try to encapsulate their own behavior starts to multiple the number of cases where different bits of code need to know about different parts of the world.
It at first seems to reflect the real world, but in reality a Rocket knows nothing about the air it is flying in and the objects it hits and blows up on. And those objects don't know anything about the Rocket, either, they are equally a'splodey whether they're hit by a Rocket or a Grenade.
The better way is Composition, the "has-a" in "is-a" versus "has-a". A Rocket has fuel. You don't say a rocket "is a fueled thing". A physics engine takes all of the things that have fuel and the things that require fuel (rocket engine) and asks "what is your fuel flow rate" and "what is your fuel consumption rate", respectively. Interfaces and Mix-Ins can be exploited to do this in a type-safe way.
Inheritance is useful when a strict tree-structure can appropriately encapsulate your needs. Unfortunately, very few things are strictly tree-like. The only times I've found a strictly tree-structured problem in the last 15 years has always involved processing language grammars. Inheritance works fine there. But even still, Haskell-style pattern matching works better. I won't go so far to say "inheritance is useless", but I will say my personal experience has been that I've learned to regret having used it in every instance.
I work on a large game, and multiple smaller games of my own, which all use a few static classes or singletons. It's never caused an issue, and I've never had such a problem with inheritance. I've never regretted using it in my code. What about Exceptions?
You don't seem to have offered a way to avoid having so much state to pass around. Where does the notification queue go? Where do the settings go? Where does the scene manager go? All the MVC controllers I have are static or singletons.
I don't see what objects have to do with no global variables or functions being allowed. There's no theoretical reason a global function can't operate on or return objects.
That's not the same thing as stateful at all. "function add(a, b) { return a + b; }" operates on two objects and returns an object, but it maintains no state. I said global state was a bad thing, not global functionality. I added a caveat that global functionality should at least be namespaced, though.
You avoid passing state around by either injecting the dependencies or returning the state transitions to some other thing that makes the state changes happen. You make explicit the relationships that the singletons hide.
http://c2.com/cgi/wiki?SingletonGlobalProblems
http://c2.com/cgi/wiki?SingletonsAreEvil
(And also: http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140... )
The basics of drag-and-drop only take a few lines to implement, but it's important to do extensive testing to find the edge cases. I found (one year ago) there were problems with jQuery UI that stopped me from making full use of it. I wound up using it for the basic dragging - it would reliably tell me mouse move events, clicks, buttons, and the mouse position, but because the droppables system would miss some events I implemented the logic surrounding detecting where the item was being dragged. Basically, whenever the item got moved, a whole bunch of calculations would run to see what object it's positioned over or near, and it's position within whatever object it's over.
If you want to do drag-and-drop programming in the browser, I recommend you write some code that allows you to pick up a DIV and drop it elsewhere on the screen. It's not trivial to do the first time, but once you understand the patterns it becomes so much easier. The techniques are useful for other similar things, like creating resize handles.
I don't think there is a way to send messages on Hacker News, and I don't yet know if you'll get alerted to replies to old posts.
Frankly HTML5 is a disaster(and no , things like WebWorkers or WebSockets are not part of the HTML5 spec before anyone jumps on me).
It's just hard to build something robust on weak foundations,but that's lot of client side developpers, making these things work even though specs are just not helping.
http://ln.hixie.ch/?start=1115899732&count=1
...which is to say, IE6 supported more event types and more configurable behaviour than HTML5 supports, but some of those extra features were just too weird, or outright crashed IE, so they didn't make it into the spec.
Appcache has ever worked flawlessly for me. IndexedDB, though, is a the feces of a dog who has eaten too much cow shit.
Why not WebSQL? Shit, even if the only implementation used is SQLite, it's better than IndexedDB which is asynchronous, can't even do a motherfucking sort, a simple enough range query or unions.
Fuck all that NoSQL crap, thank you very much.
This is crazy enough, add async-ness to the whole mess and even with promises you end up with a shitload of spaghetti code.
Right now IndexedDB is a kids playground and nothing usable at all for any serious application.