Implementing Draggable and Droppable Elements

In this example you will use custom AngularJS directives to implement a set of draggable elements containing words that can be dragged onto a set of droppable image elements. When the word is dropped on an image, it is appended to a list of words that appear below the image.

The purpose of this exercise is to show you an example of using the HTML5 drag and drop events. The example only uses the events, and the actual drag and drop functionality is built using the AngularJS mechanisms. The reason for this is to illustrate using AngularJS (plus, frankly, the HTML5 drag and drop is not well implemented and needs to be revised). Another thing illustrated in this example is appending new elements to existing ones in an AngularJS directive.

The folder structure for this example is as follows:

./server.js: Node.js web server that serves the static project files.

./images: Folder that contains the images used in the examples.

./ch11: Project folder.

./ch11/dragdrop.html: AngularJS template for the project.

./ch11/js/dragdrop.js: AngularJS application supporting the custom drag and drop directives.

The code in Listing 11.5 contains the dragdrop.js application that defines two new custom AngularJS directives, dragit and dropit. Notice that in the parent scope the dragStatus and dropStatus variables are defined; these are updated in the custom directives. This is possible because no isolate scope is defined in the directives, so they share the parent controller scope.

Notice that inside the dragit directive the HTML5 draggable attribute is added to the dragit element using the attr() method. Also in the dragit directive the dragstart, drag, and dragend event handlers are implemented. For dragstart and drag, the default behavior is to allow the drag to start and dragenter/dragleave events to fire. However, dragend does prevent the default behavior so that our custom AngularJS code can handle the drop.

Inside the dropit directive, the dragover, dragleave, dragenter, and drop are implemented. Notice that in drop we use the append method to append a <p> element to the dropit element. The value inside the paragraph comes from the scope and was set during dragstart in the dragit directive. Once again, this is possible because no isolate scopes are defined in the directives.

Listing 11.5 dragdrop.js: AngularJS Application That Implements dragit and dropit Custom AngularJS Directives to Provide Drag and Drop Functionality


01 var app = angular.module('myApp', []);
02 app.controller('myController', function($scope) {
03   $scope.dragStatus = "none";
04   $scope.dropStatus = "none";
05   $scope.dropValue = "";
06 })
07 .directive('dragit', function($document, $window) {
08   function makeDraggable(scope, element, attr) {
09     angular.element(element).attr("draggable", "true");
10     element.on('dragstart', function(event) {
11       element.addClass('dragItem'),
12       scope.$apply(function(){
13         scope.dragStatus = "Dragging " + element.html();
14         scope.dropValue = element.html();
15       });
16       event.dataTransfer.setData('Text', element.html());
17     });
18     element.on('drag', function(event) {
19       scope.$apply(function(){
20         scope.dragStatus = "X: " + event.pageX +
21                            " Y: " + event.pageY;
22       });
23     });
24     element.on('dragend', function(event) {
25       event.preventDefault();
26       element.removeClass('dragItem'),
27     });
28   }
29   return {
30     link: makeDraggable
31   };
32 })
33 .directive('dropit', function($document, $window) {
34   return {
35     restrict: 'E',
36     link: function makeDroppable(scope, element, attr){
37       element.on('dragover', function(event) {
38         event.preventDefault();
39         scope.$apply(function(){
40           scope.dropStatus = "Drag Over";
41         });
42       });
43       element.on('dragleave', function(event) {
44         event.preventDefault();
45         element.removeClass('dropItem'),
46         scope.$apply(function(){
47           scope.dropStatus = "Drag Leave";
48         });
49       });
50       element.on('dragenter', function(event) {
51         event.preventDefault();
52         element.addClass('dropItem'),
53         scope.$apply(function(){
54           scope.dropStatus = "Drag Enter";
55         });
56       });
57       element.on('drop', function(event) {
58         event.preventDefault();
59         element.removeClass('dropItem'),
60         scope.$apply(function(){
61           element.append('<p>' +
62               event.dataTransfer.getData('Text') + '</p>'),
63           scope.dropStatus = "Dropped " + scope.dropValue;
64         });
65       });
66     }
67   };
68 });


The code in Listing 11.6 implements the AngularJS template that displays the dragStatus and dropStatus values. Notice that the draggable elements are declared using the <dragit> syntax and the droppable elements are declared using the <dropit> syntax.

Figure 11.2 shows the working AngularJS application in action. As words are dragged and dropped onto the images, they are appended below the image. Also notice that the drag coordinates and drop status are displayed as well.

Listing 11.6 dragdrop.html: AngularJS Template That Uses the dragit and dropit Directives to Add Draggable and Droppable Elements to the Web Page


01 <!doctype html>
02 <html ng-app="myApp">
03 <head>
04   <title>HTML5 Draggable and Droppable Directives</title>
05   <style>
06     dropit, img, p{
07       vertical-align: top; text-align: center;
08             width: 100px;
09             display: inline-block;
10           }
11           p {
12             color: white; background-color: black;
13             font: bold 14px/16px arial;
14       margin: 0px; width: 96px;
15       border: 2px ridge grey;
16       background: linear-gradient(#888888, #000000);
17           }
18           span{
19             display:inline-block; width: 100px;
20             font: 16px/18px Georgia, serif; text-align: center;
21             padding: 2px;
22             background: linear-gradient(#FFFFFF, #888888);
23           }
24           .dragItem {
25             color: red;
26       opacity: .5;
27           }
28     .dropItem {
29       border: 3px solid red;
30       opacity: .5;
31     }
32     #dragItems {
33       width: 400px;
34     }
35   </style>
36 </head>
37 <body>
38   <h2>HTML5 Drag and Drop Components</h2>
39   <div ng-controller="myController">
40     Drag Status: {{dragStatus}}<br>
41     Drop Status: {{dropStatus}}
42     <hr>
43     <div id="dragItems">
44          <span dragit>Nature</span>
45          <span dragit>Landscape</span>
46          <span dragit>Flora</span>
47          <span dragit>Sunset</span>
48          <span dragit>Arch</span>
49          <span dragit>Beauty</span>
50          <span dragit>Inspiring</span>
51       <span dragit>Summer</span>
52       <span dragit>Fun</span>
53     </div>
54     <hr>
55     <dropit><img src="/images/arch.jpg" /></dropit>
56     <dropit><img src="/images/flower.jpg" /></dropit>
57     <dropit><img src="/images/cliff.jpg" /></dropit>
58     <dropit><img src="/images/jump.jpg" /></dropit>
59   </div>
60   <script src="http://code.angularjs.org/1.3.0/angular.min.js"></script>
61   <script src="js/dragdrop.js"></script>
62 </body>
63 </html>


Image

Figure 11.2 Using custom AngularJS directives to provide drag and drop functionality in a web page.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset