anchor.diff:  part of Tabasci;
   
  -typedef void DragCallback(DragHandler dragHandler, Element element, MouseEvent event);
   // type of a function that determines if a drag should be allowed to start
   typedef bool AllowDragStart(DragHandler dragHandler, Element element, MouseEvent event);
   
  -// TODO this should probably be a singleton. when do you drag more than one thing at a time?
  +/// The event class that is sent with drag handler stream event updates
  +class DragEvent {
  +  /// The [DragHandler] sending the event
  +  DragHandler dragHandler;
  +  /// The [Element] being dragged
  +  Element element;
  +  /// The [MouseEvent] that instigated the drag handler event
  +  MouseEvent mouseEvent;
  +  DragEvent(DragHandler this.dragHandler, Element this.element, MouseEvent this.mouseEvent);
  +}
  +
   // TODO make universal enable/disable flag
   class DragHandler {
     
  -  /// The function to be called on mouse move when dragging
  -  DragCallback drag;
  -  
  -  /// The function to be called when dragging begins
  -  DragCallback dragStart;
  -  
  -  /// The function to be called when dragging ends
  -  DragCallback dragEnd;
  -  
  -  /// The function to be called when the mouse is dragged out of the original element
  -  DragCallback dragOut;
  -  
  -  /// The function to be called when the mouse is dragged (back) into the original element
  -  DragCallback dragOver;
  +  // stream controllers
  +  StreamController<DragEvent> _dragStreamController = new StreamController<DragEvent>();
  +  StreamController<DragEvent> _dragStartStreamController = new StreamController<DragEvent>();
  +  StreamController<DragEvent> _dragEndStreamController = new StreamController<DragEvent>();
  +  StreamController<DragEvent> _dragOutStreamController = new StreamController<DragEvent>();
  +  StreamController<DragEvent> _dragOverStreamController = new StreamController<DragEvent>();
  +  /// Exposed drag handler event streams
  +  Stream<DragEvent> get onDrag => _dragStreamController.stream;
  +  Stream<DragEvent> get onDragStart => _dragStartStreamController.stream;
  +  Stream<DragEvent> get onDragEnd => _dragEndStreamController.stream;
  +  Stream<DragEvent> get onDragOut => _dragOutStreamController.stream;
  +  Stream<DragEvent> get onDragOver => _dragOverStreamController.stream;
     
     /// The function to call to determine if the drag should be allowed to start on mouse down
     AllowDragStart dragConditions;
  
positive.code:     // do actual start in case we were pending before
      _pendingToDrag();
      
      // call the drag out callback
      if(dragOut != null) {
        dragOut(this, event.currentTarget, event);
      }
    }
    void _mouseMoveHandler(MouseEvent event) {
      // do actual start in case we were pending before
      _pendingToDrag();
  
      //print("mouse move, enabled: $enabled, dragging: $_dragging");
      // call the drag callback
      // TODO is currentTarget the correct thing?
      // TODO if so, we don't really need to pass it as a para
      // because it's in event
      // TODO now that we store _currentTarget, we should probably use that
      // TODO now that we store _currentTarget, we should definitely use that,
      // TODO because this event was attached to body
      if(drag != null) {
        drag(this, _currentTarget, event);
      }
    }
    
    // the method that will be called on mouse up events when autostop is on
    void _autoStopUpHandler(MouseEvent event) {
      //print("auto stop handling, enabled: $enabled, dragging: $_dragging");
      // stop the drag
      // only call if we are currently dragging and enabled
      if((_dragStartPending || _dragging) && enabled) {
  
negative.code:     // signal that we are no longer dragging
      _dragging = false;
      
      // TODO if elements are changed during a drag, they won't be removed either
      
      // remove callbacks
      // TODO this can just be paused
      // TODO as Element?
      _cancel("mouseMove", document);
      for(Element e in _targets) {
        _cancel("mouseOver", e);
      }
      for(Element e in _targets) {
        _cancel("mouseOut", e);
      }
      
      // send end event if we weren't just pending
      if(!_dragStartPending) {
        _dragEndStreamController.add(new DragEvent(this, _currentTarget, event));
      }
      
      // clear current target
  