codementor plunker angularjs office hours - making things draggable in plunker

24
Making stuff draggable in Plunker (and other places) Creating a drag and drop directive for Angular.js CodeMentor – 9 March 2015 Geoff Goodman (@filearts)

Upload: codementor

Post on 17-Jul-2015

3.797 views

Category:

Technology


0 download

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!