text: var draganddrop = (function () {
  'use strict';
  
  // Utility
  function isFunction(obj) {
    return !!(obj && obj.constructor && obj.call && obj.apply);
  }
  function trueFn() { return true; }
  
  // Globals
  var toUpdate = [];
  var inStream;
  var order = [];
  var orderNextIdx = -1;
  var flushingUpdateQueue = false;
  var flushingStreamValue = false;
  
  function flushing() {
    return flushingUpdateQueue || flushingStreamValue;
  }
  
  
  /** @namespace */
  var flyd = {};
  
  // /////////////////////////// API ///////////////////////////////// //
  
  /**
   * Creates a new stream
   *
   * __Signature__: `a -> Stream a`
   *
   * @name flyd.stream
   * @param {*} initialValue - (Optional) the initial value of the stream
   * @return {stream} the stream
   *
   * @example
   * var n = flyd.stream(1); // Stream with initial value `1`
   * var s = flyd.stream(); // Stream with no initial value
   */
  flyd.stream = function(initialValue) {
    var endStream = createDependentStream([], trueFn);
    var s = createStream();
    s.end = endStream;
    s.fnArgs = [];
    endStream.listeners.push(s);
    if (arguments.length > 0) s(initialValue);
    return s;
  };
  // fantasy-land Applicative
  flyd.stream['fantasy-land/of'] = flyd.stream.of = flyd.stream;
  
  
  /**
   * Create a new dependent stream
   *
   * __Signature__: `(...Stream * -> Stream b -> b) -> [Stream *] -> Stream b`
   *
   * @name flyd.combine
   * @param {Function} fn - the function used to combine the streams
   * @param {Array<stream>} dependencies - the streams that this one depends on
   * @return {stream} the dependent stream
   *
   * @example
   * var n1 = flyd.stream(0);
   * var n2 = flyd.stream(0);
   * var max = flyd.combine(function(n1, n2, self, changed) {
   *   return n1() > n2() ? n1() : n2();
   * }, [n1, n2]);
   */
  function combine(fn, streams) {
    if (!streams) return (ss) => combine(fn, ss);
    var i, s, deps, depEndStreams;
    var endStream = createDependentStream([], trueFn);
    deps = []; depEndStreams = [];
    for (i = 0; i < streams.length; ++i) {
      if (streams[i] !== undefined) {
        deps.push(streams[i]);
        if (streams[i].end !== undefined) depEndStreams.push(streams[i].end);
      }
    }
    s = createDependentStream(deps, fn);
    s.depsChanged = [];
    s.fnArgs = s.deps.concat([s, s.depsChanged]);
    s.end = endStream;
    endStream.listeners.push(s);
    addListeners(depEndStreams, endStream);
    endStream.deps = depEndStreams;
    updateStream(s);
    return s;
  }
  flyd.combine = combine;
  /**
   * Returns `true` if the supplied argument is a Flyd stream and `false` otherwise.
   *
   * __Signature__: `* -> Boolean`
   *
   * @name flyd.isStream
   * @param {*} value - the value to test
   * @return {Boolean} `true` if is a Flyd streamn, `false` otherwise
   *
   * @example
   * var s = flyd.stream(1);
   * var n = 1;
   * flyd.isStream(s); //=> true
   * flyd.isStream(n); //=> false
   */
  flyd.isStream = function(stream) {
    return isFunction(stream) && 'hasVal' in stream;
  };
  
  /**
   * Invokes the body (the function to calculate the value) of a dependent stream
   *
   * By default the body of a dependent stream is only called when all the streams
   * upon which it depends has a value. `immediate` can circumvent this behaviour.
   * It immediately invokes the body of a dependent stream.
   *
   * __Signature__: `Stream a -> Stream a`
   *
   * @name flyd.immediate
   * @param {stream} stream - the dependent stream
   * @return {stream} the same stream
   *
   * @example
   * var s = flyd.stream();
   * var hasItems = flyd.immediate(flyd.combine(function(s) {
   *   return s() !== undefined && s().length > 0;
   * }, [s]);
   * console.log(hasItems()); // logs `false`. Had `immediate` not been
   *                          // used `hasItems()` would've returned `undefined`
   * s([1]);
   * console.log(hasItems()); // logs `true`.
   * s([]);
   * console.log(hasItems()); // logs `false`.
   */
  flyd.immediate = function(s) {
    if (s.depsMet === false) {
      s.depsMet = true;
      updateStream(s);
    }
    return s;
  };
  
  /**
   * Changes which `endsStream` should trigger the ending of `s`.
   *
   * __Signature__: `Stream a -> Stream b -> Stream b`
   *
   * @name flyd.endsOn
   * @param {stream} endStream - the stream to trigger the ending
   * @param {stream} stream - the stream to be ended by the endStream
   * @param {stream} the stream modified to be ended by endStream
   *
   * @example
   * var n = flyd.stream(1);
   * var killer = flyd.stream();
   * // `double` ends when `n` ends or when `killer` emits any value
   * var double = flyd.endsOn(flyd.merge(n.end, killer), flyd.combine(function(n) {
   *   return 2 * n();
   * }, [n]);
  */
  flyd.endsOn = function(endS, s) {
    detachDeps(s.end);
    endS.listeners.push(s.end);
    s.end.deps.push(endS);
    return s;
  };
  
  /**
   * Map a stream
   *
   * Returns a new stream consisting of every value from `s` passed through
   * `fn`. I.e. `map` creates a new stream that listens to `s` and
   * applies `fn` to every new value.
   * __Signature__: `(a -> result) -> Stream a -> Stream result`
   *
   * @name flyd.map
   * @param {Function} fn - the function that produces the elements of the new stream
   * @param {stream} stream - the stream to map
   * @return {stream} a new stream with the mapped values
   *
   * @example
   * var numbers = flyd.stream(0);
   * var squaredNumbers = flyd.map(function(n) { return n*n; }, numbers);
   */
  // Library functions use self callback to accept (null, undefined) update triggers.
  function map(f, s) {
    if (!s) return ss => map(f, ss);
    return combine(function(s, self) { self(f(s.val)); }, [s]);
  }
  flyd.map = map;
  
  /**
   * Chain a stream
   *
   * also known as flatMap
   *
   * Where `fn` returns a stream this function will flatten the resulting streams.
   * Every time `fn` is called the context of the returned stream will "switch" to that stream.
   *
   * __Signature__: `(a -> Stream b) -> Stream a -> Stream b`
   *
   * @name flyd.chain
   * @param {Function} fn - the function that produces the streams to be flattened
   * @param {stream} stream - the stream to map
   * @return {stream} a new stream with the mapped values
   *
   * @example
   * var filter = flyd.stream('who');
   * var items = flyd.chain(function(filter){
   *   return flyd.stream(findUsers(filter));
   * }, filter);
   */
  // flyd.chain = curryN(2,chain);
  flyd.chain = chain;
  
  /**
   * Apply a stream
   *
   * Applies the value in `s2` to the function in `s1`.
   *
   * __Signature__: `Stream (a -> b) -> Stream a -> Stream b`
   *
   * @name flyd.ap
   * @param {stream} s1 - The value to be applied
   * @param {stream} s2 - The function expecting the value
   * @return {stream} a new stream with the mapped values
   *
   * @example
   * var add = stream(a => b => a + b)
   * var n1 = stream(1)
   * var n2 = stream(2)
   *
   * var added = flyd.ap(n2, flyd.ap(n1, add)) // stream(3)
   * // can also be written using pipe
   * var added_pipe = add
   *   .pipe(ap(n1))
   *   .pipe(ap(n2));
   * added_pipe() // 3
   */
  flyd.ap = ap;
  
  /**
   * Listen to stream events
   *
   * Similar to `map` except that the returned stream is empty. Use `on` for doing
   * side effects in reaction to stream changes. Use the returned stream only if you
   * need to manually end it.
   *
   * __Signature__: `(a -> result) -> Stream a -> Stream undefined`
   *
   * @name flyd.on
   * @param {Function} cb - the callback
   * @param {stream} stream - the stream
   * @return {stream} an empty stream (can be ended)
   */
  flyd.on = function(f, s) {
    if (!s) return ss => flyd.on(f, ss);
    return combine(function(s) { f(s.val); }, [s]);
  };
  
  /**
   * Creates a new stream with the results of calling the function on every incoming
   * stream with and accumulator and the incoming value.
   *
   * __Signature__: `(a -> b -> a) -> a -> Stream b -> Stream a`
   *
   * @name flyd.scan
   * @param {Function} fn - the function to call
   * @param {*} val - the initial value of the accumulator
   * @param {stream} stream - the stream source
   * @return {stream} the new stream
   *
   * @example
   * var numbers = flyd.stream();
   * var sum = flyd.scan(function(sum, n) { return sum+n; }, 0, numbers);
   * numbers(2)(3)(5);
   * sum(); // 10
   */
  flyd.scan = function(f, acc, s) {
    if ([null, undefined].includes(acc)) return function(acc1, s1) { return flyd.scan(f, acc1, s1)}
    else if (!s) return function(s2) { return flyd.scan(f, acc, s2)}
    var ns = combine(function(s, self) {
      self(acc = f(acc, s.val));
    }, [s]);
    if (!ns.hasVal) ns(acc);
    return ns;
  };
  
  /**
   * Creates a new stream down which all values from both `stream1` and `stream2`
   * will be sent.
   *
   * __Signature__: `Stream a -> Stream a -> Stream a`
   *
   * @name flyd.merge
   * @param {stream} source1 - one stream to be merged
   * @param {stream} source2 - the other stream to be merged
   * @return {stream} a stream with the values from both sources
   *
   * @example
   * var btn1Clicks = flyd.stream();
   * button1Elm.addEventListener(btn1Clicks);
   * var btn2Clicks = flyd.stream();
   * button2Elm.addEventListener(btn2Clicks);
   * var allClicks = flyd.merge(btn1Clicks, btn2Clicks);
   */
  flyd.merge = function(s1, s2) {
    if (!s2) return (ss) => flyd.merge(s1, ss);
    var s = flyd.immediate(combine(function(s1, s2, self, changed) {
      if (changed[0]) {
        self(changed[0]());
      } else if (s1.hasVal) {
        self(s1.val);
      } else if (s2.hasVal) {
        self(s2.val);
      }
    }, [s1, s2]));
    flyd.endsOn(combine(function() {
      return true;
    }, [s1.end, s2.end]), s);
    return s;
  };
  
  /**
   * Creates a new stream resulting from applying `transducer` to `stream`.
   *
   * __Signature__: `Transducer -> Stream a -> Stream b`
   *
   * @name flyd.transduce
   * @param {Transducer} xform - the transducer transformation
   * @param {stream} source - the stream source
   * @return {stream} the new stream
   *
   * @example
   * var t = require('transducers.js');
   *
   * var results = [];
   * var s1 = flyd.stream();
   * var tx = t.compose(t.map(function(x) { return x * 2; }), t.dedupe());
   * var s2 = flyd.transduce(tx, s1);
   * flyd.combine(function(s2) { results.push(s2()); }, [s2]);
   * s1(1)(1)(2)(3)(3)(3)(4);
   * results; // => [2, 4, 6, 8]
   */
  flyd.transduce = function(xform, source) {
    if (!source) return ss => flyd.transduce(xform, ss)
    xform = xform(new StreamTransformer());
    return combine(function(source, self) {
      var res = xform['@@transducer/step'](undefined, source.val);
      if (res && res['@@transducer/reduced'] === true) {
        self.end(true);
        return res['@@transducer/value'];
      } else {
        return res;
      }
    }, [source]);
  };
  
  /**
   * Returns `fn` curried to `n`. Use this function to curry functions exposed by
   * modules for Flyd.
   *
   * @name flyd.curryN
   * @function
   * @param {Integer} arity - the function arity
   * @param {Function} fn - the function to curry
   * @return {Function} the curried function
   *
   * @example
   * function add(x, y) { return x + y; };
   * var a = flyd.curryN(2, add);
   * a(2)(4) // => 6
   */
  flyd.curryN = (number, fn) =>
    function _curry(...args) {
      if (arguments.length >= fn.length) return fn(...args);
      return (...argsN)=> _curry(...args, ...argsN);
    };
  
  /**
   * Returns a new stream identical to the original except every
   * value will be passed through `f`.
   *
   * _Note:_ This function is included in order to support the fantasy land
   * specification.
   *
   * __Signature__: Called bound to `Stream a`: `(a -> b) -> Stream b`
   *
   * @name stream.map
   * @param {Function} function - the function to apply
   * @return {stream} a new stream with the values mapped
   *
   * @example
   * var numbers = flyd.stream(0);
   * var squaredNumbers = numbers.map(function(n) { return n*n; });
   */
  function boundMap(f) { return map(f, this); }
  
  /**
   * Returns the result of applying function `fn` to this stream
   *
   * __Signature__: Called bound to `Stream a`: `(a -> Stream b) -> Stream b`
   *
   * @name stream.pipe
   * @param {Function} fn - the function to apply
   * @return {stream} A new stream
   *
   * @example
   * var numbers = flyd.stream(0);
   * var squaredNumbers = numbers.pipe(flyd.map(function(n){ return n*n; }));
   */
  function operator_pipe(f) { return f(this) }
  
  function boundChain(f) {
    return chain(f, this);
  }
  
  function chain(f, s) {
    // Internal state to end flat map stream
    if (!s) return ss => chain(f, ss);
    var flatEnd = flyd.stream(1);
    var internalEnded = flyd.on(function() {
      var alive = flatEnd() - 1;
      flatEnd(alive);
      if (alive <= 0) {
        flatEnd.end(true);
      }
    });
  
    internalEnded(s.end);
    var last = flyd.stream();
    var flatStream = flyd.combine(function(s, own) {
      last.end(true);
      // Our fn stream makes streams
      var newS = f(s());
      flatEnd(flatEnd() + 1);
      internalEnded(newS.end);
  
      // Update self on call -- newS is never handed out so deps don't matter
      last = map(own, newS);
    }, [s]);
  
    flyd.endsOn(flatEnd.end, flatStream);
  
    return flatStream;
  }
  
  flyd.fromPromise = function fromPromise(p) {
    var s = flyd.stream();
    p.then(function(val) {
      s(val);
      s.end(true);
    });
    return s;
  };
  
  flyd.flattenPromise = function flattenPromise(s) {
    return combine(function(s, self) {
      s().then(self);
    }, [s])
  };
  
  
  /**
   * Returns a new stream which is the result of applying the
   * functions from `this` stream to the values in `stream` parameter.
   *
   * `this` stream must be a stream of functions.
   *
   * _Note:_ This function is included in order to support the fantasy land
   * specification.
   *
   * __Signature__: Called bound to `Stream (a -> b)`: `a -> Stream b`
   *
   * @name stream.ap
   * @param {stream} stream - the values stream
   * @return {stream} a new stream with the functions applied to values
   *
   * @example
   * var add = flyd.curryN(2, function(x, y) { return x + y; });
   * var numbers1 = flyd.stream();
   * var numbers2 = flyd.stream();
   * var addToNumbers1 = flyd.map(add, numbers1);
   * var added = addToNumbers1.ap(numbers2);
   */
  function ap(s2, s1) {
    if (!s1) return ss => ap(s2, ss);
    return combine(function(s1, s2, self) { self(s1.val(s2.val)); }, [s1, s2]);
  }
  
  function boundAp(s2) {
    return ap(s2, this);
  }
  
  /**
   * @private
   */
  function fantasy_land_ap(s1) {
    return ap(this, s1);
  }
  
  /**
   * Get a human readable view of a stream
   * @name stream.toString
   * @return {String} the stream string representation
   */
  function streamToString() {
    return 'stream(' + this.val + ')';
  }
  
  /**
   * @name stream.end
   * @memberof stream
   * A stream that emits `true` when the stream ends. If `true` is pushed down the
   * stream the parent stream ends.
   */
  
  /**
   * @name stream.of
   * @function
   * @memberof stream
   * Returns a new stream with `value` as its initial value. It is identical to
   * calling `flyd.stream` with one argument.
   *
   * __Signature__: Called bound to `Stream (a)`: `b -> Stream b`
   *
   * @param {*} value - the initial value
   * @return {stream} the new stream
   *
   * @example
   * var n = flyd.stream(1);
   * var m = n.of(1);
   */
  
  // /////////////////////////// PRIVATE ///////////////////////////////// //
  /**
   * @private
   * Create a stream with no dependencies and no value
   * @return {Function} a flyd stream
   */
  function createStream() {
    function s() {
      return s._push.apply(this, arguments);
    }
    s._push = function(n) {
      if (arguments.length === 0) return s.val
      updateStreamValue(n, s);
      return s
    };
    s.hasVal = false;
    s.val = undefined;
    s.updaters = [];
    s.listeners = [];
    s.queued = false;
    s.end = undefined;
  
    // fantasy-land compatibility
    s.ap = boundAp;
    s['fantasy-land/map'] = s.map = boundMap;
    s['fantasy-land/ap'] = fantasy_land_ap;
    s['fantasy-land/of'] = s.of = flyd.stream;
    s['fantasy-land/chain'] = s.chain = boundChain;
  
    s.pipe = operator_pipe;
  
    // According to the fantasy-land Applicative specification
    // Given a value f, one can access its type representative via the constructor property:
    // `f.constructor.of`
    s.constructor = flyd.stream;
  
    s.toJSON = function() {
      return s.val;
    };
    s.toString = streamToString;
    return s;
  }
  
  /**
   * @private
   * Create a dependent stream
   * @param {Array<stream>} dependencies - an array of the streams
   * @param {Function} fn - the function used to calculate the new stream value
   * from the dependencies
   * @return {stream} the created stream
   */
  function createDependentStream(deps, fn) {
    var s = createStream();
    s.fn = fn;
    s.deps = deps;
    s.depsMet = false;
    s.depsChanged = deps.length > 0 ? [] : undefined;
    s.shouldUpdate = false;
    addListeners(deps, s);
    return s;
  }
  
  /**
   * @private
   * Check if all the dependencies have values
   * @param {stream} stream - the stream to check depencencies from
   * @return {Boolean} `true` if all dependencies have vales, `false` otherwise
   */
  function initialDependenciesMet(stream) {
    stream.depsMet = stream.deps.every(function(s) {
      return s.hasVal;
    });
    return stream.depsMet;
  }
  
  function dependenciesAreMet(stream) {
    return stream.depsMet === true || initialDependenciesMet(stream);
  }
  
  function isEnded(stream) {
    return stream.end && stream.end.val === true;
  }
  
  function listenersNeedUpdating(s) {
    return s.listeners.some(function(s) { return s.shouldUpdate; });
  }
  
  /**
   * @private
   * Update a dependent stream using its dependencies in an atomic way
   * @param {stream} stream - the stream to update
   */
  function updateStream(s) {
    if (isEnded(s) || !dependenciesAreMet(s)) return;
    if (inStream !== undefined) {
      updateLaterUsing(updateStream, s);
      return;
    }
    inStream = s;
    if (s.depsChanged) s.fnArgs[s.fnArgs.length - 1] = s.depsChanged;
    var returnVal = s.fn.apply(s.fn, s.fnArgs);
    if (returnVal !== undefined) {
      s(returnVal);
    }
    inStream = undefined;
    if (s.depsChanged !== undefined) s.depsChanged = [];
    s.shouldUpdate = false;
    if (flushing() === false) flushUpdate();
    if (listenersNeedUpdating(s)) {
      if (!flushingStreamValue) s(s.val);
      else {
        s.listeners.forEach(function(listener) {
          if (listener.shouldUpdate) updateLaterUsing(updateStream, listener);
        });
      }
    }
  }
  
  /**
   * @private
   * Update the dependencies of a stream
   * @param {stream} stream
   */
  function updateListeners(s) {
    var i, o, list;;;
    var listeners = s.listeners;
    for (i = 0; i < listeners.length; ++i) {
      list = listeners[i];
      if (list.end === s) {
        endStream(list);
      } else {
        if (list.depsChanged !== undefined) list.depsChanged.push(s);
        list.shouldUpdate = true;
        findDeps(list);
      }
    }
    for (; orderNextIdx >= 0; --orderNextIdx) {
      o = order[orderNextIdx];
      if (o.shouldUpdate === true) updateStream(o);
      o.queued = false;
    }
  }
  
  /**
   * @private
   * Add stream dependencies to the global `order` queue.
   * @param {stream} stream
   * @see updateDeps
   */
  function findDeps(s) {
    var i;
    var listeners = s.listeners;
    if (s.queued === false) {
      s.queued = true;
      for (i = 0; i < listeners.length; ++i) {
        findDeps(listeners[i]);
      }
      order[++orderNextIdx] = s;
    }
  }
  
  function updateLaterUsing(updater, stream) {
    toUpdate.push(stream);
    stream.updaters.push(updater);
    stream.shouldUpdate = true;
  }
  
  /**
   * @private
   */
  function flushUpdate() {
    flushingUpdateQueue = true;
    while (toUpdate.length > 0) {
      var stream = toUpdate.shift();
      var nextUpdateFn = stream.updaters.shift();
      if (nextUpdateFn && stream.shouldUpdate) nextUpdateFn(stream);
    }
    flushingUpdateQueue = false;
  }
  
  /**
   * @private
   * Push down a value into a stream
   * @param {stream} stream
   * @param {*} value
   */
  function updateStreamValue(n, s) {
    s.val = n;
    s.hasVal = true;
    if (inStream === undefined) {
      flushingStreamValue = true;
      updateListeners(s);
      if (toUpdate.length > 0) flushUpdate();
      flushingStreamValue = false;
    } else if (inStream === s) {
      markListeners(s, s.listeners);
    } else {
      updateLaterUsing(function(s) { updateStreamValue(n, s); }, s);
    }
  }
  
  /**
   * @private
   */
  function markListeners(s, lists) {
    var i, list;
    for (i = 0; i < lists.length; ++i) {
      list = lists[i];
      if (list.end !== s) {
        if (list.depsChanged !== undefined) {
          list.depsChanged.push(s);
        }
        list.shouldUpdate = true;
      } else {
        endStream(list);
      }
    }
  }
  
  /**
   * @private
   * Add dependencies to a stream
   * @param {Array<stream>} dependencies
   * @param {stream} stream
   */
  function addListeners(deps, s) {
    for (var i = 0; i < deps.length; ++i) {
      deps[i].listeners.push(s);
    }
  }
  
  /**
   * @private
   * Removes an stream from a dependency array
   * @param {stream} stream
   * @param {Array<stream>} dependencies
   */
  function removeListener(s, listeners) {
    var idx = listeners.indexOf(s);
    listeners[idx] = listeners[listeners.length - 1];
    listeners.length--;
  }
  
  /**
   * @private
   * Detach a stream from its dependencies
   * @param {stream} stream
   */
  function detachDeps(s) {
    for (var i = 0; i < s.deps.length; ++i) {
      removeListener(s, s.deps[i].listeners);
    }
    s.deps.length = 0;
  }
  
  /**
   * @private
   * Ends a stream
   */
  function endStream(s) {
    if (s.deps !== undefined) detachDeps(s);
    if (s.end !== undefined) detachDeps(s.end);
  }
  
  /**
   * @private
   */
  /**
   * @private
   * transducer stream transformer
   */
  function StreamTransformer() { }
  StreamTransformer.prototype['@@transducer/init'] = function() { };
  StreamTransformer.prototype['@@transducer/result'] = function() { };
  StreamTransformer.prototype['@@transducer/step'] = function(s, v) { return v; };
  
  var lib = flyd;
  
  var takeuntil = lib.curryN(2, function(src, term) {
    return lib.endsOn(lib.merge(term, src.end), lib.combine(function(src, self) {
      self(src());
    }, [src]));
  });
  
  document.addEventListener('DOMContentLoaded', function() {
    var dragElm = document.getElementById('drag');
  
    var mousedown  = lib.stream();
    var mousemove  = lib.stream();
    var mouseup    = lib.stream();
  
    dragElm.addEventListener('mousedown', mousedown);
    document.addEventListener('mousemove', mousemove);
    document.addEventListener('mouseup', mouseup);
  
    var mousedrag = lib.chain(function(md) {
      var startX = md.offsetX, startY = md.offsetY;
  
      return takeuntil(lib.map(function(mm) {
        mm.preventDefault();
  
        return {
          left: mm.clientX - startX,
          top: mm.clientY - startY
        };
      }, mousemove), mouseup);
    }, mousedown);
  
    lib.on(function(pos) {
      dragElm.style.top = pos.top + 'px';
      dragElm.style.left = pos.left + 'px';
    }, mousedrag);
  });
  
  var script = {
  
  };
  
  return script;
  
  }());
  