| 
          /** | 
        
        
           | 
          
 | 
        
        
           | 
           The MIT License (MIT) | 
        
        
           | 
          
 | 
        
        
           | 
           Copyright (c) 2015 Simon Friis Vindum | 
        
        
           | 
          
 | 
        
        
           | 
           Permission is hereby granted, free of charge, to any person obtaining a copy | 
        
        
           | 
           of this software and associated documentation files (the "Software"), to deal | 
        
        
           | 
           in the Software without restriction, including without limitation the rights | 
        
        
           | 
           to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
        
        
           | 
           copies of the Software, and to permit persons to whom the Software is | 
        
        
           | 
           furnished to do so, subject to the following conditions: | 
        
        
           | 
          
 | 
        
        
           | 
           The above copyright notice and this permission notice shall be included in all | 
        
        
           | 
           copies or substantial portions of the Software. | 
        
        
           | 
          
 | 
        
        
           | 
           THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
        
        
           | 
           IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
        
        
           | 
           FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
        
        
           | 
           AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
        
        
           | 
           LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
        
        
           | 
           OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
        
        
           | 
           SOFTWARE. | 
        
        
           | 
          
 | 
        
        
           | 
           */ | 
        
        
           | 
          
 | 
        
        
           | 
          (function (root, factory) { | 
        
        
           | 
              if (typeof define === 'function' && define.amd) { | 
        
        
           | 
                  define([], factory); // AMD. Register as an anonymous module. | 
        
        
           | 
              } else if (typeof exports === 'object') { | 
        
        
           | 
                  module.exports = factory(); // NodeJS | 
        
        
           | 
              } else { // Browser globals (root is window) | 
        
        
           | 
                  root.flyd = factory(); | 
        
        
           | 
              } | 
        
        
           | 
          }(this, function () { | 
        
        
           | 
          
 | 
        
        
           | 
              'use strict'; | 
        
        
           | 
          
 | 
        
        
           | 
              function isFunction(obj) { | 
        
        
           | 
                  return !!(obj && obj.constructor && obj.call && obj.apply); | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
          // Globals | 
        
        
           | 
              var toUpdate = []; | 
        
        
           | 
              var inStream; | 
        
        
           | 
          
 | 
        
        
           | 
              function map(f, s) { | 
        
        
           | 
                  return stream([s], function(self) { self(f(s())); }); | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function boundMap(f) { return map(f, this); } | 
        
        
           | 
          
 | 
        
        
           | 
              var scan = curryN(3, function(f, acc, s) { | 
        
        
           | 
                  var ns = stream([s], function() { | 
        
        
           | 
                      return (acc = f(acc, s())); | 
        
        
           | 
                  }); | 
        
        
           | 
                  if (!ns.hasVal) ns(acc); | 
        
        
           | 
                  return ns; | 
        
        
           | 
              }); | 
        
        
           | 
          
 | 
        
        
           | 
              var merge = curryN(2, function(s1, s2) { | 
        
        
           | 
                  var s = immediate(stream([s1, s2], function(n, changed) { | 
        
        
           | 
                      return changed[0] ? changed[0]() | 
        
        
           | 
                          : s1.hasVal  ? s1() | 
        
        
           | 
                          : s2(); | 
        
        
           | 
                  })); | 
        
        
           | 
                  endsOn(stream([s1.end, s2.end], function(self, changed) { | 
        
        
           | 
                      return true; | 
        
        
           | 
                  }), s); | 
        
        
           | 
                  return s; | 
        
        
           | 
              }); | 
        
        
           | 
          
 | 
        
        
           | 
              function ap(s2) { | 
        
        
           | 
                  var s1 = this; | 
        
        
           | 
                  return stream([s1, s2], function() { return s1()(s2()); }); | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function initialDepsNotMet(stream) { | 
        
        
           | 
                  stream.depsMet = stream.deps.every(function(s) { | 
        
        
           | 
                      return s.hasVal; | 
        
        
           | 
                  }); | 
        
        
           | 
                  return !stream.depsMet; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function updateStream(s) { | 
        
        
           | 
                  if ((s.depsMet !== true && initialDepsNotMet(s)) || | 
        
        
           | 
                      (s.end !== undefined && s.end.val === true)) return; | 
        
        
           | 
                  inStream = s; | 
        
        
           | 
                  var returnVal = s.fn(s, s.depsChanged); | 
        
        
           | 
                  if (returnVal !== undefined) { | 
        
        
           | 
                      s(returnVal); | 
        
        
           | 
                  } | 
        
        
           | 
                  inStream = undefined; | 
        
        
           | 
                  if (s.depsChanged !== undefined) { | 
        
        
           | 
                      while (s.depsChanged.length > 0) s.depsChanged.shift(); | 
        
        
           | 
                  } | 
        
        
           | 
                  s.shouldUpdate = false; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              var order = []; | 
        
        
           | 
              var orderNextIdx = -1; | 
        
        
           | 
          
 | 
        
        
           | 
              function findDeps(s) { | 
        
        
           | 
                  var i, listeners = s.listeners; | 
        
        
           | 
                  if (s.queued === false) { | 
        
        
           | 
                      s.queued = true; | 
        
        
           | 
                      for (i = 0; i < listeners.length; ++i) { | 
        
        
           | 
                          findDeps(listeners[i]); | 
        
        
           | 
                      } | 
        
        
           | 
                      order[++orderNextIdx] = s; | 
        
        
           | 
                  } | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function updateDeps(s) { | 
        
        
           | 
                  var i, o, list, 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; | 
        
        
           | 
                  } | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function flushUpdate() { | 
        
        
           | 
                  while (toUpdate.length > 0) updateDeps(toUpdate.shift()); | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function isStream(stream) { | 
        
        
           | 
                  return isFunction(stream) && 'hasVal' in stream; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function streamToString() { | 
        
        
           | 
                  return 'stream(' + this.val + ')'; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function createStream() { | 
        
        
           | 
                  function s(n) { | 
        
        
           | 
                      var i, list; | 
        
        
           | 
                      if (arguments.length === 0) { | 
        
        
           | 
                          return s.val; | 
        
        
           | 
                      } else { | 
        
        
           | 
                          if (n !== undefined && n !== null && isFunction(n.then)) { | 
        
        
           | 
                              n.then(s); | 
        
        
           | 
                              return; | 
        
        
           | 
                          } | 
        
        
           | 
                          s.val = n; | 
        
        
           | 
                          s.hasVal = true; | 
        
        
           | 
                          if (inStream === undefined) { | 
        
        
           | 
                              updateDeps(s); | 
        
        
           | 
                              if (toUpdate.length > 0) flushUpdate(); | 
        
        
           | 
                          } else if (inStream === s) { | 
        
        
           | 
                              for (i = 0; i < s.listeners.length; ++i) { | 
        
        
           | 
                                  list = s.listeners[i]; | 
        
        
           | 
                                  if (list.end !== s) { | 
        
        
           | 
                                      if (list.depsChanged !== undefined) { | 
        
        
           | 
                                          list.depsChanged.push(s); | 
        
        
           | 
                                      } | 
        
        
           | 
                                      list.shouldUpdate = true; | 
        
        
           | 
                                  } else { | 
        
        
           | 
                                      endStream(list); | 
        
        
           | 
                                  } | 
        
        
           | 
                              } | 
        
        
           | 
                          } else { | 
        
        
           | 
                              toUpdate.push(s); | 
        
        
           | 
                          } | 
        
        
           | 
                          return s; | 
        
        
           | 
                      } | 
        
        
           | 
                  } | 
        
        
           | 
                  s.hasVal = false; | 
        
        
           | 
                  s.val = undefined; | 
        
        
           | 
                  s.listeners = []; | 
        
        
           | 
                  s.queued = false; | 
        
        
           | 
                  s.end = undefined; | 
        
        
           | 
          
 | 
        
        
           | 
                  s.map = boundMap; | 
        
        
           | 
                  s.ap = ap; | 
        
        
           | 
                  s.of = stream; | 
        
        
           | 
                  s.toString = streamToString; | 
        
        
           | 
          
 | 
        
        
           | 
                  return s; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function createDependentStream(deps, fn) { | 
        
        
           | 
                  var i, s = createStream(); | 
        
        
           | 
                  s.fn = fn; | 
        
        
           | 
                  s.deps = deps; | 
        
        
           | 
                  s.depsMet = false; | 
        
        
           | 
                  s.depsChanged = fn.length > 1 ? [] : undefined; | 
        
        
           | 
                  s.shouldUpdate = false; | 
        
        
           | 
                  for (i = 0; i < deps.length; ++i) { | 
        
        
           | 
                      deps[i].listeners.push(s); | 
        
        
           | 
                  } | 
        
        
           | 
                  return s; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function immediate(s) { | 
        
        
           | 
                  if (s.depsMet === false) { | 
        
        
           | 
                      s.depsMet = true; | 
        
        
           | 
                      updateStream(s); | 
        
        
           | 
                      if (toUpdate.length > 0) flushUpdate(); | 
        
        
           | 
                  } | 
        
        
           | 
                  return s; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function removeListener(s, listeners) { | 
        
        
           | 
                  var idx = listeners.indexOf(s); | 
        
        
           | 
                  listeners[idx] = listeners[listeners.length - 1]; | 
        
        
           | 
                  listeners.length--; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function detachDeps(s) { | 
        
        
           | 
                  for (var i = 0; i < s.deps.length; ++i) { | 
        
        
           | 
                      removeListener(s, s.deps[i].listeners); | 
        
        
           | 
                  } | 
        
        
           | 
                  s.deps.length = 0; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function endStream(s) { | 
        
        
           | 
                  if (s.deps !== undefined) detachDeps(s); | 
        
        
           | 
                  if (s.end !== undefined) detachDeps(s.end); | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function endsOn(endS, s) { | 
        
        
           | 
                  detachDeps(s.end); | 
        
        
           | 
                  endS.listeners.push(s.end); | 
        
        
           | 
                  s.end.deps.push(endS); | 
        
        
           | 
                  return s; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function stream(arg, fn) { | 
        
        
           | 
                  var i, s, deps, depEndStreams; | 
        
        
           | 
                  var endStream = createDependentStream([], function() { return true; }); | 
        
        
           | 
                  if (arguments.length > 1) { | 
        
        
           | 
                      deps = []; depEndStreams = []; | 
        
        
           | 
                      for (i = 0; i < arg.length; ++i) { | 
        
        
           | 
                          if (arg[i] !== undefined) { | 
        
        
           | 
                              deps.push(arg[i]); | 
        
        
           | 
                              if (arg[i].end !== undefined) depEndStreams.push(arg[i].end); | 
        
        
           | 
                          } | 
        
        
           | 
                      } | 
        
        
           | 
                      s = createDependentStream(deps, fn); | 
        
        
           | 
                      s.end = endStream; | 
        
        
           | 
                      endStream.listeners.push(s); | 
        
        
           | 
                      endsOn(createDependentStream(depEndStreams, function() { return true; }, true), s); | 
        
        
           | 
                      updateStream(s); | 
        
        
           | 
                      if (toUpdate.length > 0) flushUpdate(); | 
        
        
           | 
                  } else { | 
        
        
           | 
                      s = createStream(); | 
        
        
           | 
                      s.end = endStream; | 
        
        
           | 
                      endStream.listeners.push(s); | 
        
        
           | 
                      if (arguments.length === 1) s(arg); | 
        
        
           | 
                  } | 
        
        
           | 
                  return s; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              var transduce = curryN(2, function(xform, source) { | 
        
        
           | 
                  xform = xform(new StreamTransformer()); | 
        
        
           | 
                  return stream([source], function(self) { | 
        
        
           | 
                      var res = xform['@@transducer/step'](undefined, source()); | 
        
        
           | 
                      if (res && res['@@transducer/reduced'] === true) { | 
        
        
           | 
                          self.end(true); | 
        
        
           | 
                          return res['@@transducer/value']; | 
        
        
           | 
                      } else { | 
        
        
           | 
                          return res; | 
        
        
           | 
                      } | 
        
        
           | 
                  }); | 
        
        
           | 
              }); | 
        
        
           | 
          
 | 
        
        
           | 
              function StreamTransformer() { } | 
        
        
           | 
              StreamTransformer.prototype['@@transducer/init'] = function() { }; | 
        
        
           | 
              StreamTransformer.prototype['@@transducer/result'] = function() { }; | 
        
        
           | 
              StreamTransformer.prototype['@@transducer/step'] = function(s, v) { return v; }; | 
        
        
           | 
          
 | 
        
        
           | 
          // Own curry implementation snatched from Ramda | 
        
        
           | 
          // Figure out something nicer later on | 
        
        
           | 
              var _ = {placeholder: true}; | 
        
        
           | 
          
 | 
        
        
           | 
          // Detect both own and Ramda placeholder | 
        
        
           | 
              function isPlaceholder(p) { | 
        
        
           | 
                  return p === _ || (p && p.ramda === 'placeholder'); | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function toArray(arg) { | 
        
        
           | 
                  var arr = []; | 
        
        
           | 
                  for (var i = 0; i < arg.length; ++i) { | 
        
        
           | 
                      arr[i] = arg[i]; | 
        
        
           | 
                  } | 
        
        
           | 
                  return arr; | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
          // Modified versions of arity and curryN from Ramda | 
        
        
           | 
              function ofArity(n, fn) { | 
        
        
           | 
                  if (arguments.length === 1) { | 
        
        
           | 
                      return ofArity.bind(undefined, n); | 
        
        
           | 
                  } | 
        
        
           | 
                  switch (n) { | 
        
        
           | 
                      case 0: | 
        
        
           | 
                          return function () { | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 1: | 
        
        
           | 
                          return function (a0) { | 
        
        
           | 
                              void a0; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 2: | 
        
        
           | 
                          return function (a0, a1) { | 
        
        
           | 
                              void a1; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 3: | 
        
        
           | 
                          return function (a0, a1, a2) { | 
        
        
           | 
                              void a2; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 4: | 
        
        
           | 
                          return function (a0, a1, a2, a3) { | 
        
        
           | 
                              void a3; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 5: | 
        
        
           | 
                          return function (a0, a1, a2, a3, a4) { | 
        
        
           | 
                              void a4; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 6: | 
        
        
           | 
                          return function (a0, a1, a2, a3, a4, a5) { | 
        
        
           | 
                              void a5; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 7: | 
        
        
           | 
                          return function (a0, a1, a2, a3, a4, a5, a6) { | 
        
        
           | 
                              void a6; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 8: | 
        
        
           | 
                          return function (a0, a1, a2, a3, a4, a5, a6, a7) { | 
        
        
           | 
                              void a7; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 9: | 
        
        
           | 
                          return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) { | 
        
        
           | 
                              void a8; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      case 10: | 
        
        
           | 
                          return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { | 
        
        
           | 
                              void a9; | 
        
        
           | 
                              return fn.apply(this, arguments); | 
        
        
           | 
                          }; | 
        
        
           | 
                      default: | 
        
        
           | 
                          throw new Error('First argument to arity must be a non-negative integer no greater than ten'); | 
        
        
           | 
                  } | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              function curryN(length, fn) { | 
        
        
           | 
                  return ofArity(length, function () { | 
        
        
           | 
                      var n = arguments.length; | 
        
        
           | 
                      var shortfall = length - n; | 
        
        
           | 
                      var idx = n; | 
        
        
           | 
                      while (--idx >= 0) { | 
        
        
           | 
                          if (isPlaceholder(arguments[idx])) { | 
        
        
           | 
                              shortfall += 1; | 
        
        
           | 
                          } | 
        
        
           | 
                      } | 
        
        
           | 
                      if (shortfall <= 0) { | 
        
        
           | 
                          return fn.apply(this, arguments); | 
        
        
           | 
                      } else { | 
        
        
           | 
                          var initialArgs = toArray(arguments); | 
        
        
           | 
                          return curryN(shortfall, function () { | 
        
        
           | 
                              var currentArgs = toArray(arguments); | 
        
        
           | 
                              var combinedArgs = []; | 
        
        
           | 
                              var idx = -1; | 
        
        
           | 
                              while (++idx < n) { | 
        
        
           | 
                                  var val = initialArgs[idx]; | 
        
        
           | 
                                  combinedArgs[idx] = isPlaceholder(val) ? currentArgs.shift() : val; | 
        
        
           | 
                              } | 
        
        
           | 
                              return fn.apply(this, combinedArgs.concat(currentArgs)); | 
        
        
           | 
                          }); | 
        
        
           | 
                      } | 
        
        
           | 
                  }); | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
              return { | 
        
        
           | 
                  stream: stream, | 
        
        
           | 
                  isStream: isStream, | 
        
        
           | 
                  transduce: transduce, | 
        
        
           | 
                  merge: merge, | 
        
        
           | 
                  reduce: scan, // Legacy | 
        
        
           | 
                  scan: scan, | 
        
        
           | 
                  endsOn: endsOn, | 
        
        
           | 
                  map: curryN(2, map), | 
        
        
           | 
                  curryN: curryN, | 
        
        
           | 
                  _: _, | 
        
        
           | 
                  immediate: immediate, | 
        
        
           | 
              }; | 
        
        
           | 
          
 | 
        
        
           | 
          })); |