budde377/Part

View on GitHub
dart/part/lib/src/elements_changeable_list.dart

Summary

Maintainability
Test Coverage
part of elements;

class ChangeableList {

  final Element list;

  LIElement _dragging_li, _currently_expanded;

  List<LIElement> _dividers = new List<LIElement>();

  static Map<Element, ChangeableList> _cache = new Map<Element, ChangeableList>();

  factory ChangeableList(Element list) => _cache.putIfAbsent(list, ()=>new ChangeableList._internal(list));

  ChangeableList._internal(this.list){
    _setUp();
  }

  LIElement _getTargetFromEvent(Event ev){
    var target = ev.target;

    if(!(target is Element)){
      return null;
    }

    while(!(target is LIElement) && target != null){
      target = target.parent;
    }

    if(!list.children.contains(target)){
      return null;
    }
    return target;
  }

  void _setUp(){
    list.querySelectorAll("li").forEach((LIElement li){
      li.draggable = true;
    });


    list.onDragStart.listen((MouseEvent ev){
      var target = _getTargetFromEvent(ev);
      if(target == null){
        return;
      }

      LIElement li = target;
      ev.dataTransfer..setData("Text", li.hashCode.toString())
                     ..effectAllowed = "move";

      _dragging_li = li;
      li.classes.add("dragging");
      _setUpDividers();

    });

    list.onDragEnd.listen((MouseEvent ev){
      var target = _getTargetFromEvent(ev);
      if(target == null){
        return;
      }

      LIElement li = target;
      _dragging_li = null;
      li.classes.remove("dragging");
      _clearDividers();
    });

    list.onDragOver.listen((MouseEvent ev){
      var target = _getTargetFromEvent(ev);
      if(target == null){
        return;
      }

      LIElement li = target.classes.contains('divider')?target:
        (target.marginEdge.top+target.marginEdge.height~/2 >= ev.page.y?target.previousElementSibling:target.nextElementSibling);
      ev.preventDefault();

      if(_currently_expanded != null && _currently_expanded != li){
        _currently_expanded.classes.remove("expanded");
      } else if(_currently_expanded == li){
        return;
      }

      li.classes.add('expanded');
      _currently_expanded = li;


    });


    list.onDrop.listen((MouseEvent ev){
      var li = _getTargetFromEvent(ev);
      if(li == null ||  _currently_expanded == null){
        return;
      }

      if(li == _dragging_li || _dragging_li.nextElementSibling == li || _dragging_li.previousElementSibling == li){
        return;
      }


      list.insertBefore(_dragging_li, _currently_expanded);
      ev.preventDefault();

      _clearDividers();
      list.dispatchEvent(new Event("change", canBubble: true, cancelable:false));


    });


  }

  void _setUpDividers(){
    _dividers = new List<LIElement>();
    list.children.toList().forEach((LIElement li){
      var divider = new LIElement();
      _dividers.add(divider);
      list.insertBefore(divider, li);
      divider.classes.add('divider');
    });
    var li = new LIElement();
    _dividers.add(li);
    li.classes.add('divider');
    list.append(li);
    list.classes.add("incl_dividers");
  }

  void _clearDividers(){
    list.classes.remove("incl_dividers");
    _dividers.toList().forEach((LIElement li){
      li.remove();
      _dividers.remove(li);
    });
  }

  void append(LIElement li){
    list.append(li);
    li.draggable = true;
  }

}