AngularJS - Using shared object to communicate between controllers & directives

by vacationlabs

HTML

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
<div ng-app="MyModule" ng-controller="MyController">
    <p>Pick a color: <select ng-options="color for color in ['red', 'blue', 'yellow']" ng-model="box1.color"></select></p>
    <p>My coordinates are: top={{ box1.top }} &amp; left={{ box1.left }}</p>
    <div draggable="" options="box1"></div>
    
    <hr />
    
    <p>Pick a color: <select ng-options="color for color in ['red', 'blue', 'yellow']" ng-model="box2.color"></select></p>
    <p>My coordinates are: top={{ box2.top }} &amp; left={{ box2.left }}</p>
    <div draggable="" options="box2"></div>

</div>

CSS

.draggable {
    width: 100px;
    height: 100px;
    position: relative;
}

.draggable h3 {
    position: absolute;
    left: 20px;
    top: 15px;
}
}

JavaScript

$('#draggable').draggable();

var mod = angular.module('MyModule', []);
mod.controller('MyController', ['$scope', function($scope) {
    var can_drop = function(top, left, i) {
        if(i==1) {
            return !is_overlapping(top, left, $scope.box2.top, $scope.box2.left);
        } else {
            return !is_overlapping(top, left, $scope.box1.top, $scope.box1.left);
        }
    }
    
    var is_overlapping = function(t1, l1, t2, l2) {
        return Math.abs(t1-t2)<=100 && Math.abs(l1-l2)<=100;
    }
    
    $scope.box1 = {
        'color' : 'red',
        'can_drop' : can_drop,
        'top' : null,
        'left' : null,
        'i' : 1
    };
    
    $scope.box2 = {
        'color' : 'blue',
        'can_drop' : can_drop,
        'top' : null,
        'left' : null,
        'i' : 2
    };
    

}]);

mod.directive('draggable', function() {
    return {
        'restrict' : 'A',
        'scope' : {
            'options' : '='
        },
        'template' : '<div class="draggable"><h3>Drag me around</h3></div>',
        'replace' : true,
        'link' : function(scope, element, attrs) {
            var can_drop_fn = attrs.canDrop;
            element.draggable();
            scope.options.top = element.position().top;
            scope.options.left = element.position().left;
            
            scope.$watch('options.color', function(color) {
                element.css('background', color);
            });

            element.bind('dragstop', function(evt, ui) {
                if(scope.options.can_drop(ui.offset.top, ui.offset.left, scope.options.i)) {
                    scope.$apply(function() {
                        scope.options.top = ui.offset.top;
                        scope.options.left = ui.offset.left;
                    });
                } else {
                    element.css({
                        'top' : scope.options.top,
                        'left' : scope.options.left
                    });
                }
 ...