<!DOCTYPE html>
<html>
<head>
    <script src="//cdn.jsdelivr.net/jquery/2.1.1/jquery.min.js"></script>
    <script src="//cdn.jsdelivr.net/bootstrap.todc/3.1.1/js/bootstrap.min.js"></script>
    <script src="//cdn.jsdelivr.net/angularjs/1.2.9/angular.min.js"></script>
    <link rel="stylesheet" href="//cdn.jsdelivr.net/bootstrap.todc/3.1.1/css/bootstrap.min.css" />
    <script src="script.js"></script>
    <link rel="stylesheet" href="style.css">
</head>
<body ng-app ng-controller="Main" >
    <div class="container container-narrow">
        <h1>Tree View</h1>
        <ul class="list-unstyled">
            <li ng-repeat="data in datas track by $index" mp-drop="drop">
                <span style="cursor:pointer;" ng-click="data.open=!data.open">
             		<i  class="glyphicon" ng-class="{'glyphicon-folder-close':!data.open,'glyphicon-folder-open':data.open}"></i>&nbsp;
              		{{data.title}}
              </span>
                <ul ng-if="data.feeds && data.open" class="feed-list">
                    <li ng-repeat="feed in data.feeds track by $index"><a href="#" data-data-transfer="feed" mp-drag="drag">{{feed.title}}</a>
                    </li>
                </ul>
            </li>
        </ul>
    </div>
</body>
</html>
function Main($scope, datas) {
  $scope.datas = datas;
}

angular.module('ng')
  .directive('mpDrag', function($timeout, $window, $document) {
    return {
      scope: {
        dataTransfer: '=',
        mpDrag: '='
      },
      link: function($scope, element, attrs) {
        var el;
        var $body = angular.element('body');

        function makeDragImage(originalElement) {
          var el = angular.element("<div>").append(originalElement.clone());
          el.addClass('drag-image');
          el.attr('name', 'drag-image');
          el.css({
            'position': 'absolute',
            'display': 'block',
            'z-index': 1000
          });
          return el;
        }
        $timeout(function() {

          element.attr('draggable', 'draggable');
          element.on('dragstart', function(e) {
            element.addClass('mp-drag');
            el = makeDragImage(element);
            $body.css('position', 'relative');
            $body.append(el);
            //setting the drag image doesnt work on my computer(windows7)
            //e.originalEvent.dataTransfer.setDragImage(el.get(0),0,0);
            e.originalEvent.dataTransfer.setData("text/plain", angular.toJson($scope.dataTransfer || ""));
          })
            .on('dragend', function(e) {
              element.removeClass('mp-drag');
              el.remove();
            })
            .on('drag', function(e) {
              if (e.originalEvent.clientX) {
                el.css({
                  'top': e.originalEvent.clientY + 10,
                  'left': e.originalEvent.clientX + 10
                });
              } else {
                el.css('display', 'none');
              }
            });
        });
      }
    };
  })
  .directive('mpDrop', function($timeout) {
    return {
      link: function($scope, element) {
        $timeout(function() {
          element.on('dragenter', function(e) {
            e.preventDefault();
          })
            .on('dragover', function(e) {
              element.addClass('mp-dragover');
              e.preventDefault();
            })
            .on('dragleave', function(e) {
              element.removeClass('mp-dragover');
            })
            .on('drop', function(e) {
              element.removeClass('mp-dragover');
              //console.log('drop', e, e.originalEvent.dataTransfer.getData('text/plain'));
              if ($scope.mpDrop instanceof Function) {
                $scope.mpDrop(e.originalEvent);
              }
              e.preventDefault();
            })
        });
      }
    };
  })
  .constant('datas', [{
    "id": 0,
    "title": "Haskell",
    "open": true,
    "feeds": [{
      "id": 0,
      "title": "velit aliquip"
    }, {
      "id": 1,
      "title": "in commodo"
    }, {
      "id": 2,
      "title": "occaecat elit"
    }, {
      "id": 3,
      "title": "minim adipisicing"
    }, {
      "id": 4,
      "title": "culpa non"
    }, {
      "id": 5,
      "title": "do magna"
    }]
  }, {
    "id": 1,
    "title": "Javascript",
    "feeds": [{
      "id": 0,
      "title": "do aute"
    }]
  }, {
    "id": 2,
    "title": "Microsoft",
    "feeds": [{
      "id": 0,
      "title": "aliquip est"
    }, {
      "id": 1,
      "title": "enim dolor"
    }, {
      "id": 2,
      "title": "cillum ex"
    }]
  }, {
    "id": 3,
    "title": "UX",
    "feeds": [{
      "id": 0,
      "title": "tempor ea"
    }, {
      "id": 1,
      "title": "quis nulla"
    }, {
      "id": 2,
      "title": "ex dolore"
    }, {
      "id": 3,
      "title": "eu voluptate"
    }, {
      "id": 4,
      "title": "cillum quis"
    }, {
      "id": 5,
      "title": "ut ipsum"
    }, {
      "id": 6,
      "title": "mollit culpa"
    }, {
      "id": 7,
      "title": "exercitation nostrud"
    }, {
      "id": 8,
      "title": "excepteur occaecat"
    }, {
      "id": 9,
      "title": "ipsum adipisicing"
    }]
  }, {
    "id": 4,
    "title": "Java",
    "feeds": [{
      "id": 0,
      "title": "amet quis"
    }, {
      "id": 1,
      "title": "laborum labore"
    }, {
      "id": 2,
      "title": "esse ipsum"
    }, {
      "id": 3,
      "title": "do deserunt"
    }, {
      "id": 4,
      "title": "sunt officia"
    }, {
      "id": 5,
      "title": "eu officia"
    }, {
      "id": 6,
      "title": "velit deserunt"
    }, {
      "id": 7,
      "title": "cupidatat sint"
    }, {
      "id": 8,
      "title": "occaecat ea"
    }]
  }]); // Code goes here
.feed-list {
    list-style-type: none;
    padding-left: 20px;
}
.mp-drag {
    opacity: 0.9;
    cursor: move;
}
.mp-dragover {
    opacity: 0.4;
}
.drag-image{
  background-color: #FFF;
}