codementor plunker angularjs office hours - making things draggable in plunker
TRANSCRIPT
Making things draggable in Plunker
Making stuff draggable in Plunker (and other places)
Creating a drag and drop directive for Angular.js
CodeMentor 9 March 2015
Geoff Goodman (@filearts)
May 22, 2008
Presentation title
Page #
Who is this guy?
Hi, Im Geoff Goodman
Twitter: @filearts
Github: @ggoodman
During the day, I value businesses atEY (Ernst & Young)
At night, I build Plunker which is an in-browser editor for front-end code.
May 22, 2008
Presentation title
Page #
Like I said, Plunker is an in-browser code editor
A code editor is only half done if you cant drag things around
Im not really good with Powerpoint. Bear with my crappy black and white presentation and gif animations
May 22, 2008
Presentation title
Page #
May 22, 2008
Presentation title
Page #
Fail
In case it wasnt obvious, instead of dragging files, some useless selection range happened.
May 22, 2008
Presentation title
Page #
In a modern editor, you should be able to drag files around in a file tree. (Show video)
Also, wouldnt it be handy if you could re-organize your workspace however you wanted? (Show video)
May 22, 2008
Presentation title
Page #
Prior art
https://github.com/codef0rmer/angular-dragdrop - Wraps jQuery UI
https://github.com/a5hik/ng-sortable - Comprehensive, dependency-free list reordering and transferral
https://github.com/logicbomb/lvlDragDrop - Also low-level, dependency-free drag and drop based on html5 api
Figuring out what I needed
I know that I have things that I want to drag
I know that there are only certain places to drop stuff
I know that only certain things can be dropped in certain places
Things to drag: files, directories, panes
I also thought it would be great if you could drag files to and from the desktop
But you cant drag a folder into a file, you cant drag a folder into a child folder etc..
You need to be able to define what can be dragged where
May 22, 2008
Presentation title
Page #
Making this in Angular.js
Angular lets me define how I want certain things to behave straight in the markup
These are called directives
They are not the easiest thing to learn and understand
But they are crazy powerful
HTML5 also defines a great API for drag and drop (Spec)
Little segway into Angular (this wont be a deep dive into Angular, sorry!)
The HTML5 api is a little unintuitive to begin with, but is really powerful and actually quite simple to use!
- Need to cancel events to opt-in
May 22, 2008
Presentation title
Page #
Overcome API limitations
The drag and drop pioneer is now a black sheep
IE only allows Text and URL as the data types
Using our own layer on top, we can support any data
Angular internals
Three directives:
drag-container
drop-container
drop-area
And one service to share drag state between the directives: $dragging.
A service is an instance of an object that can be injected into other bits of an angular application. A service is a singleton instance so injecting the $dragging service will always give me the same instance. I use this to store a reference to the object identified as being dragged. I can also set the full mime-type of the data being dragged to work around a quirk of IEs.
May 22, 2008
Presentation title
Page #
What I came up with:
drag-container
Determines the data being dragged (drag-container attribute) and the type of that data (mime-type attribute)
Call preventDefault() on the dragstart event and the browser will start dragging! In the event handler, I set the drag data.
I also need to call some methods of the dataTransfer object to tell the browser what the mime-type of my data is and pass the browser the data itself. Even though IE pioneered this api, it has moved forward since then. In IE, you cannot set the type to anything but text and url. Fortunately, by having a service instance
May 22, 2008
Presentation title
Page #
drop-container
Defines a region that will accept any drop that passes the accept test.
Accepts event handlers, figures out appropriate target and delegates event.
So for the workspace of the next version of Plunker, I wanted people to be able to reorganize their workspace in a simple and intuitive way. A tiling window manager is an appropriate example of what I wanted. You can drag a file or pane into the workspace, split an existing pane horizontally, vertically or simply replace the pane depending on where you drop within the overall panes surface.
May 22, 2008
Presentation title
Page #
Delegating to targets
Create a virtual point for each target
Calculate minimum distance b/w mouse and point
top
top-right
right
bottom-right
bottom
bottom-left
left
top-left
center
For the plunker workspace, I have top, right, bottom and left targets that will trigger splits. I have a center target that will trigger a pane replace.
May 22, 2008
Presentation title
Page #
drop-target
Defines a potential region of the drop-container that can respond to drag and drop events
Can by styled by css to give drop hints
The dr
May 22, 2008
Presentation title
Page #
Linking the directives up
drop-targets require an instance of a drop-container in their DDO:
.directive("dropTarget", ["$parse", function ($parse) {
return {
restrict: "A",
require: ["^dropContainer", "dropTarget"],
controller: "DropTargetController",
controllerAs: "dropTarget",
link: function ($scope, $element, $attrs, ctrls) {
var dropContainer = ctrls[0];
var dropTarget = ctrls[1];
var anchor = $attrs.dropTarget || "center";
dropContainer.addDropTarget(anchor, dropTarget);
May 22, 2008
Presentation title
Page #
drop-targets are just attachment points
They are not designed to have content
When active, an -active css class is added so that they can: e.g. be shown or given dashed borders
Creating them gives you regions of the drop-container that can respond to events that relate only to that region
Event handling
HTML5 gives us a bunch of events. I chose a few to expose:
on-drag-start, on-drag-end
on-drag-enter, on-drag-leave
on-drag-over
on-drop
Angular can inject special objects exposed to those handlers, like $event and data
In Angular, you can use the $parse service to parse the value of your elements attributes into a function that can be run on any scope-like object and another locals object and will run the angular expression as if it was in the context defined by the $scope and locals.
The injectable $event and data object are made available via this locals concept.
The library uses this mechanism for the events listed on this slide.
Note that on-drag-start and on-drag-end are only available to drag-containers whereas all the other events are only available on drop-container and drop-targets.
May 22, 2008
Presentation title
Page #
What this lets you do
Trello-style storyboards lists: DEMO
Re-orderable lists by:
Having a leading and trailing drop-target for each list item
Splicing before or after the target element on-drag-enter
Sliding puzzle: DEMO
More complex behaviours: DEMO
Caveats
Determining if something is draggable must be synchronous
This means zip-building
May 22, 2008
Presentation title
Page #
But what about the code?
The code is MIT-licensed on github: https://github.com/ggoodman/angular-drag-drop
Feel free to ping me if you have questions on Twitter: @filearts or @plnkrco
One more thing
With a hack here and some duct tape there
DEMO
Thanks for listening!