<!DOCTYPE html>
<html>

  <head>
    <script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script data-require="angular.js@*" data-semver="1.2.14" src="http://code.angularjs.org/1.2.14/angular.js"></script>
    <link href="style.css" rel="stylesheet" />
    <script src="nested-sortable.js"></script>
    <script src="script.js"></script>
  </head>

  <body ng-app="MyApp">
    <span ng-controller="SortCtrl">
      <span id="main">
        <ol ng-model="list" ui-nested-sortable="sortableOptions">
          <li ui-nested-sortable-item="" ng-repeat="item in list">
            <div ui-nested-sortable-handle="" ng-class="item.nodes != null ? 'groupItem':'filterItem'">
              <span ng-click="toggleAndor()" class="andor" data-nodrag="" ng-style="{visibility: item.andor.length > 0 ? 'visible' : 'hidden'}">{{item.andor}}</span>
              <span class="field"> {{item.field}}</span>
              <span> {{item.op}}</span>
            </div>
            <ol ng-model="item.nodes" ui-nested-sortable="sortableOptions">
              <li ui-nested-sortable-item="" ng-repeat="item in item.nodes">
                <div ui-nested-sortable-handle="" ng-class="item.nodes != null ? 'groupItem':'filterItem'">
                  <span ng-click="toggleAndor()" class="andor" data-nodrag="" ng-style="{visibility: item.andor.length > 0 ? 'visible' : 'hidden'}">{{item.andor}}</span>
                  <span class="field"> {{item.field}}</span>
                  <span> {{item.op}}</span>
                </div>
              </li>
            </ol>
          </li>
        </ol>
      </span>
      <span id="debug">
        <pre>{{list | json}}</pre>
      </span>
    </span>
  </body>

</html>
(function() {
  'use strict';

  angular.module('MyApp', ['ui.nestedSortable'])
  .controller('SortCtrl', function($scope) {
    $scope.list = [{
      "andor": "",
      "op":"equals",
      "field": "country"
      },{
        "andor": "AND",
        "nodes":[{
          "andor": "",
          "op":"equals",
          "field": "state"
          },{
          "andor": "AND",
          "op":"equals",
          "field": "city"
          },{
          "andor": "AND",
          "op":"equals",
          "field": "town"
          }]
      },{
      "andor": "OR",
      "op":"equals",
      "field": "county"
      }];
      
    $scope.options = [{
      "name":"Equals",
      "op":"equals"
    }];
    
    $scope.selected;
      
    $scope.toggleAndor = function() {
      if(this.item.andor == "AND")
        this.item.andor = "OR";
      else
        this.item.andor = "AND"
    }

    $scope.selectedItem = {};
    
    $scope.sortableOptions = {
      stop: function(scope, modelData, elements) {
        console.log($("#main li:first-child"));
      }
    };

    $scope.options = {
      itemClicked: function(sourceItem, clickedElmDragged) {
        $scope.$apply(function() {
          $scope.selectedItem = sourceItem;
        });
      }

    };

    $scope.remove = function(scope) {
      //scope.removeItem();
      var index = scope.$index;
      if (index > -1) {
        scope.sortableModelValue.splice(index, 1)[0];
      }
    };
    
    $scope.newSubItem = function(scope) {
      var itemData = scope.itemData();
      itemData.items.push({
        id: itemData.id * 10 + itemData.items.length,
        title: itemData.title + '.' + (itemData.items.length + 1),
        items: []
      });
    };
  })
})();
#main {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 25%;
  background: gray;
}

#main ol{
  padding: 0;
}

#main li{
  list-style-type: none;
  margin-left: 15px;
  margin-right: 15px;
  margin-bottom: 10px;
}

#debug {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 75%;
  right: 0px;
  background: white;
  font-size: 8px;
}

.groupItem {
  background: blue;
  border-left: 1px solid white;
  border-right: 1px solid white;
  border-top: 1px solid white;
  padding: 5px;
}

.groupItem+ol{
  background: lightblue;
  border-left: 1px solid white;
  border-right: 1px solid white;
  border-bottom: 1px solid white;
  min-height: 30px;
  border-radius: 0 0 8px 8px;
  padding-top: 10px !important;
}

.filterItem{
  border: 1px solid white;
  background: red;
  padding: 5px;
  border-radius: 0 0 8px 8px;
}

.andor{
  position: static;
  cursor: pointer;
  border: 1px solid lightgray;
  background: lightgray;
  border-radius: 5px;;
}

.nestedSortable-placeholder{
  border: 3px dashed orange;
  list-style: none;
}
/**
 * @license Angular NestedSortable v1.3.8
 * (c) 2010-2014. https://github.com/JimLiu/Angular-NestedSortable
 * License: MIT
 */
!function(){"use strict";angular.module("ui.nestedSortable",[]).constant("nestedSortableConfig",{listClass:"nestedSortable-list",itemClass:"nestedSortable-item",handleClass:"nestedSortable-handle",placeHolderClass:"nestedSortable-placeholder",dragClass:"nestedSortable-drag",subListClass:"nestedSortable-sublist",threshold:30})}(),function(){"use strict";angular.module("ui.nestedSortable").factory("$helper",["$document","$window",function($document,$window){return{height:function(element){return element.prop("scrollHeight")},width:function(element){return element.prop("scrollWidth")},offset:function(element){var boundingClientRect=element[0].getBoundingClientRect();return{width:element.prop("offsetWidth"),height:element.prop("offsetHeight"),top:boundingClientRect.top+($window.pageYOffset||$document[0].body.scrollTop||$document[0].documentElement.scrollTop),left:boundingClientRect.left+($window.pageXOffset||$document[0].body.scrollLeft||$document[0].documentElement.scrollLeft)}},positionStarted:function(e,target){var pos={};return pos.offsetX=e.pageX-this.offset(target).left,pos.offsetY=e.pageY-this.offset(target).top,pos.startX=pos.lastX=e.pageX,pos.startY=pos.lastY=e.pageY,pos.nowX=pos.nowY=pos.distX=pos.distY=pos.dirAx=0,pos.dirX=pos.dirY=pos.lastDirX=pos.lastDirY=pos.distAxX=pos.distAxY=0,pos},positionMoved:function(e,pos,firstMoving){pos.lastX=pos.nowX,pos.lastY=pos.nowY,pos.nowX=e.pageX,pos.nowY=e.pageY,pos.distX=pos.nowX-pos.lastX,pos.distY=pos.nowY-pos.lastY,pos.lastDirX=pos.dirX,pos.lastDirY=pos.dirY,pos.dirX=0===pos.distX?0:pos.distX>0?1:-1,pos.dirY=0===pos.distY?0:pos.distY>0?1:-1;var newAx=Math.abs(pos.distX)>Math.abs(pos.distY)?1:0;return firstMoving?(pos.dirAx=newAx,void(pos.moving=!0)):(pos.dirAx!==newAx?(pos.distAxX=0,pos.distAxY=0):(pos.distAxX+=Math.abs(pos.distX),0!==pos.dirX&&pos.dirX!==pos.lastDirX&&(pos.distAxX=0),pos.distAxY+=Math.abs(pos.distY),0!==pos.dirY&&pos.dirY!==pos.lastDirY&&(pos.distAxY=0)),void(pos.dirAx=newAx))}}}])}(),function(){"use strict";angular.module("ui.nestedSortable").controller("NestedSortableController",["$scope","nestedSortableConfig",function($scope){$scope.sortableElement=null,$scope.sortableModelValue=null,$scope.callbacks=null,$scope.items=[],$scope.initSortable=function(element){$scope.sortableElement=element},$scope.insertSortableItem=function(index,itemModelData){$scope.sortableModelValue.splice(index,0,itemModelData),$scope.$apply()},$scope.initSubItemElement=function(subElement){subElement.parentScope=$scope},$scope.parentItemScope=function(){return $scope.sortableElement.parentItemScope},$scope.level=function(){var parentItem=$scope.parentItemScope();return parentItem?parentItem.level()+1:1};var collapseOrExpand=function(scope,collapsed){for(var i=0;i<scope.items.length;i++){collapsed?scope.items[i].collapse():scope.items[i].expand();var subScope=scope.items[i].subScope();subScope&&collapseOrExpand(subScope,collapsed)}};$scope.collapseAll=function(){collapseOrExpand($scope,!0)},$scope.expandAll=function(){collapseOrExpand($scope,!1)}}])}(),function(){"use strict";angular.module("ui.nestedSortable").controller("NestedSortableHandleController",["$scope","$attrs","nestedSortableConfig",function($scope){$scope.initHandle=function(element){element.attr("sortable-elment-type","handle")}}])}(),function(){"use strict";angular.module("ui.nestedSortable").controller("NestedSortableItemController",["$scope","$attrs","nestedSortableConfig",function($scope){$scope.sortableItemElement=null,$scope.subSortableElement=null,$scope.collapsed=!1,$scope.initItem=function(element){$scope.sortableItemElement=element,$scope.initSubItemElement(element),$scope.items.splice($scope.$index,0,$scope),element.attr("sortable-elment-type","item")},$scope.removeItem=function(){var index=$scope.$index;if(index>-1){var item=$scope.sortableModelValue.splice(index,1)[0];return $scope.items.splice(index,1)[0],"$apply"!=$scope.$root.$$phase&&"$digest"!=$scope.$root.$$phase&&$scope.$apply(),item}return null};var subLevel=0,countSubLevel=function(scope){for(var count=0,i=0;i<scope.items.length;i++){var itemSub=scope.items[i].subScope();itemSub&&(count=1,countSubLevel(itemSub))}subLevel+=count};$scope.maxSubLevels=function(){return subLevel=0,$scope.subScope()&&countSubLevel($scope.subScope()),subLevel},$scope.itemData=function(){return $scope.sortableModelValue[$scope.$index]},$scope.setSubSortableElement=function(subElement){$scope.subSortableElement=subElement,subElement&&(subElement.parentItemScope=$scope)},$scope.parentScope=function(){return $scope.sortableItemElement.parentScope},$scope.subScope=function(){if(!$scope.subSortableElement)return null;var subScope=$scope.subSortableElement.scope();return subScope&&!subScope.sortableModelValue&&(subScope=null),subScope},$scope.accept=function(sourceItemScope,destScope,destIndex){return $scope.callbacks.accept(sourceItemScope.itemData(),sourceItemScope,destScope,destIndex)},$scope.childAccept=function(sourceItemScope,destScope){var destIndex=destScope?destScope.items.length:0;return $scope.subScope()&&$scope.subScope().callbacks.accept(sourceItemScope.itemData(),sourceItemScope,destScope,destIndex)},$scope.prev=function(){return $scope.$index>0?$scope.items[$scope.$index-1]:null},$scope.toggle=function(){$scope.collapsed=!$scope.collapsed},$scope.collapse=function(){$scope.collapsed=!0},$scope.expand=function(){$scope.collapsed=!1}}])}(),function(){"use strict";angular.module("ui.nestedSortable").directive("uiNestedSortable",["nestedSortableConfig","$window",function(nestedSortableConfig){return{require:["ngModel","?^uiNestedSortableItem"],restrict:"A",scope:!0,controller:"NestedSortableController",link:function(scope,element,attrs,controllersArr){var callbacks={accept:null},config={};angular.extend(config,nestedSortableConfig),config.listClass&&element.addClass(config.listClass);var ngModel=controllersArr[0],itemCtrl=controllersArr[1];scope.initSortable(element),itemCtrl&&(config.subListClass&&element.addClass(config.subListClass),scope.setSubSortableElement(element)),ngModel&&(ngModel.$render=function(){scope.sortableModelValue=ngModel.$modelValue}),callbacks.accept=function(){return!0},callbacks.orderChanged=function(){},callbacks.itemRemoved=function(){},callbacks.itemAdded=function(){},callbacks.itemMoved=function(){},callbacks.itemClicked=function(){},callbacks.start=function(){},callbacks.move=function(){},callbacks.stop=function(){},scope.$watch(attrs.uiNestedSortable,function(newVal){angular.forEach(newVal,function(value,key){callbacks[key]&&"function"==typeof value&&(callbacks[key]=value)}),scope.callbacks=callbacks},!0),element.on("$destroy",function(){itemCtrl&&(scope.setSubSortableElement(null),element.parentItemScope=null)})}}}])}(),function(){"use strict";angular.module("ui.nestedSortable").directive("uiNestedSortableHandle",["nestedSortableConfig","$helper","$window","$document",function(nestedSortableConfig,$helper,$window,$document){return{require:"^uiNestedSortableItem",restrict:"A",controller:"NestedSortableHandleController",link:function(scope,element){var placeElm,hiddenPlaceElm,targetScope,sourceIndex,destIndex,sameParent,pos,dragElm,dragItemElm,dragItem,firstMoving,targetItem,targetBefore,clickedElm,clickedElmDragged,sourceItem,elements,config={};angular.extend(config,nestedSortableConfig),scope.initHandle(element),config.handleClass&&element.addClass(config.handleClass);var hasTouch="ontouchstart"in window,copyArray=function(sourceArray){for(var arrayCopy=[],i=0;i<sourceArray.length;i++)arrayCopy.push(sourceArray[i]);return arrayCopy},dragStartEvent=function(e){if(hasTouch||2!=e.button&&3!=e.which){clickedElm=angular.element(e.target),clickedElmDragged=!1,sourceItem=clickedElm.scope().itemData();for(var target=angular.element(e.target),nodrag=function(targetElm){return"undefined"!=typeof targetElm.attr("nodrag")||"undefined"!=typeof targetElm.attr("data-nodrag")};target&&target[0]&&target[0]!=element;){if(nodrag(target))return;target=target.parent()}var moveObj=e;hasTouch&&(void 0!==e.targetTouches?moveObj=e.targetTouches.item(0):void 0!==e.originalEvent&&void 0!==e.originalEvent.targetTouches&&(moveObj=e.originalEvent.targetTouches.item(0))),e.preventDefault(),firstMoving=!0,targetScope=null,sourceIndex=scope.$index,dragItem={index:scope.$index,items:copyArray(scope.items),scope:scope,reset:function(index,scope,dragItemScope){sameParent=scope.sortableElement==dragItemScope.sortableElement,sameParent&&index>sourceIndex&&index--,destIndex=index,this.index=index,this.scope=scope,this.items=copyArray(scope.items);var i=this.items.indexOf(dragItemScope);i>-1&&this.items.splice(i,1),this.items.splice(index,0,dragItemScope)},prev:function(){return this.index>0?this.items[this.index-1]:null},next:function(){return this.index<this.items.length-1?this.items[this.index+1]:null}};var tagName=scope.sortableItemElement.prop("tagName");if("tr"===tagName.toLowerCase()){placeElm=angular.element($window.document.createElement(tagName));var tdElm=angular.element($window.document.createElement("td")).addClass(config.placeHolderClass);placeElm.append(tdElm)}else placeElm=angular.element($window.document.createElement(tagName)).addClass(config.placeHolderClass);hiddenPlaceElm=angular.element($window.document.createElement(tagName)),dragItemElm=scope.sortableItemElement,pos=$helper.positionStarted(moveObj,dragItemElm),placeElm.css("height",$helper.height(dragItemElm)+"px"),dragElm=angular.element($window.document.createElement(scope.sortableElement.prop("tagName"))).addClass(scope.sortableElement.attr("class")).addClass(config.dragClass),dragElm.css("width",$helper.width(dragItemElm)+"px"),dragElm.css("z-index",9999),dragItemElm.after(placeElm),dragItemElm.after(hiddenPlaceElm),dragItemElm[0].parentNode.removeChild(dragItemElm[0]),dragElm.append(dragItemElm),angular.element($window.document.body).bind("mouseleave",dragEndEvent),$document.find("body").append(dragElm),dragElm.css({left:moveObj.pageX-pos.offsetX+"px",top:moveObj.pageY-pos.offsetY+"px"}),elements={placeholder:placeElm,dragging:dragElm},scope.callbacks.start(scope,sourceItem,elements),hasTouch?(angular.element($document).bind("touchend",dragEndEvent),angular.element($document).bind("touchcancel",dragEndEvent),angular.element($document).bind("touchmove",dragMoveEvent)):(angular.element($document).bind("mouseup",dragEndEvent),angular.element($document).bind("mousemove",dragMoveEvent))}},dragMoveEvent=function(e){var currentAccept,prev,childAccept,moveObj=e;if(clickedElmDragged=!0,hasTouch&&(void 0!==e.touches?moveObj=e.touches.item(0):void 0!==e.originalEvent&&void 0!==e.originalEvent.touches&&(moveObj=e.originalEvent.touches.item(0))),dragElm){if(e.preventDefault(),dragElm.css({left:moveObj.pageX-pos.offsetX+"px",top:moveObj.pageY-pos.offsetY+"px"}),$helper.positionMoved(e,pos,firstMoving),firstMoving)return void(firstMoving=!1);if(pos.dirAx&&pos.distAxX>=config.threshold&&(pos.distAxX=0,sameParent=!1,pos.distX>0&&(prev=dragItem.prev(),prev&&!prev.collapsed&&(childAccept=prev.childAccept(scope,prev.subScope()),childAccept&&(prev.subSortableElement.append(placeElm),destIndex=prev.subScope().items.length,targetScope=prev.subScope(),dragItem.reset(destIndex,targetScope,scope)))),pos.distX<0)){var next=dragItem.next();next||(targetItem=dragItem.scope.parentItemScope(),targetItem&&(currentAccept=targetItem.accept(scope,targetItem,targetItem.$index+1),currentAccept&&(targetItem.sortableItemElement.after(placeElm),destIndex=targetItem.$index+1,targetScope=targetItem,dragItem.reset(destIndex,targetItem.parentScope(),scope))))}var moveRight=$helper.offset(dragElm).left-$helper.offset(placeElm).left>=config.threshold,targetX=moveObj.pageX-$window.document.body.scrollLeft,targetY=moveObj.pageY-(window.pageYOffset||$window.document.documentElement.scrollTop);angular.isFunction(dragElm.hide)&&dragElm.hide(),$window.document.elementFromPoint(targetX,targetY);var targetElm=angular.element($window.document.elementFromPoint(targetX,targetY));if(angular.isFunction(dragElm.show)&&dragElm.show(),"item"!=targetElm.attr("sortable-elment-type")&&"handle"!=targetElm.attr("sortable-elment-type"))return;targetItem=targetElm.scope(),targetElm=targetItem.sortableItemElement;var targetItemData=null;if(targetItem&&(targetItemData=targetItem.itemData()),!pos.dirAx){sameParent=!1;var targetOffset=$helper.offset(targetElm);targetBefore=$helper.offset(placeElm).top>targetOffset.top?$helper.offset(dragElm).top<targetOffset.top+$helper.height(targetElm)/2:moveObj.pageY<targetOffset.top,targetBefore?(prev=targetItem.prev(),childAccept=prev&&prev.childAccept(scope,targetItem.subScope()),currentAccept=targetItem.accept(scope,targetItem.parentScope(),targetItem.$index),!childAccept||!moveRight&&currentAccept||prev.collapsed?currentAccept&&(targetElm[0].parentNode.insertBefore(placeElm[0],targetElm[0]),destIndex=targetItem.$index,targetScope=targetItem.parentScope(),dragItem.reset(destIndex,targetScope,scope)):(targetItem=prev,targetItem.subSortableElement.append(placeElm),destIndex=targetItem.subScope().items.length,targetScope=targetItem.subScope(),dragItem.reset(destIndex,targetScope,scope))):(childAccept=targetItem.childAccept(scope,targetItem.subScope()),currentAccept=targetItem.accept(scope,targetItem.parentScope(),targetItem.$index+1),!childAccept||!moveRight&&currentAccept||targetItem.collapsed?currentAccept&&(targetElm.after(placeElm),destIndex=targetItem.$index+1,targetScope=targetItem.parentScope(),dragItem.reset(destIndex,targetScope,scope)):(targetItem.subSortableElement.append(placeElm),destIndex=targetItem.subScope().items.length,targetScope=targetItem.subScope(),dragItem.reset(destIndex,targetScope,scope)))}scope.callbacks.move(scope,sourceItem,elements)}},dragEndEvent=function(e){if(dragElm&&(e&&e.preventDefault(),dragItemElm[0].parentNode.removeChild(dragItemElm[0]),hiddenPlaceElm.replaceWith(dragItemElm),placeElm.remove(),dragElm.remove(),dragElm=null,scope.callbacks.itemClicked(sourceItem,clickedElmDragged),scope.callbacks.stop(scope,sourceItem,elements),targetScope&&(!sameParent||sourceIndex!=destIndex))){var source=scope.removeItem();targetScope.insertSortableItem(destIndex,source,scope),sameParent?scope.callbacks.orderChanged(scope.sortableElement.scope(),source,sourceIndex,destIndex):(scope.callbacks.itemRemoved(scope.sortableElement.scope(),source,sourceIndex),targetScope.callbacks.itemAdded(targetScope,source,destIndex),scope.callbacks.itemMoved(scope.sortableElement.scope(),source,sourceIndex,targetScope,destIndex))}hasTouch?(angular.element($document).unbind("touchend",dragEndEvent),angular.element($document).unbind("touchcancel",dragEndEvent),angular.element($document).unbind("touchmove",dragMoveEvent)):(angular.element($document).unbind("mouseup",dragEndEvent),angular.element($document).unbind("mousemove",dragMoveEvent),angular.element($window.document.body).unbind("mouseleave",dragEndEvent))};hasTouch?element.bind("touchstart",dragStartEvent):element.bind("mousedown",dragStartEvent)}}}])}(),function(){"use strict";angular.module("ui.nestedSortable").directive("uiNestedSortableItem",["nestedSortableConfig",function(nestedSortableConfig){return{require:"^uiNestedSortable",restrict:"A",controller:"NestedSortableItemController",link:function(scope,element){var config={};angular.extend(config,nestedSortableConfig),config.itemClass&&element.addClass(config.itemClass),scope.initItem(element)}}}])}();