"use strict";

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

(function (f) {
  if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === "object" && typeof module !== "undefined") {
    module.exports = f();
  } else if (typeof define === "function" && define.amd) {
    define([], f);
  } else {
    var g;if (typeof window !== "undefined") {
      g = window;
    } else if (typeof global !== "undefined") {
      g = global;
    } else if (typeof self !== "undefined") {
      g = self;
    } else {
      g = this;
    }g.snabbdom = f();
  }
})(function () {
  var define, module, exports;return function e(t, n, r) {
    function s(o, u) {
      if (!n[o]) {
        if (!t[o]) {
          var a = typeof require == "function" && require;if (!u && a) return a(o, !0);if (i) return i(o, !0);var f = new Error("Cannot find module '" + o + "'");throw f.code = "MODULE_NOT_FOUND", f;
        }var l = n[o] = { exports: {} };t[o][0].call(l.exports, function (e) {
          var n = t[o][1][e];return s(n ? n : e);
        }, l, l.exports, e, t, n, r);
      }return n[o].exports;
    }var i = typeof require == "function" && require;for (var o = 0; o < r.length; o++) {
      s(r[o]);
    }return s;
  }({ 1: [function (require, module, exports) {
      function createElement(tagName) {
        return document.createElement(tagName);
      }

      function createElementNS(namespaceURI, qualifiedName) {
        return document.createElementNS(namespaceURI, qualifiedName);
      }

      function createTextNode(text) {
        return document.createTextNode(text);
      }

      function insertBefore(parentNode, newNode, referenceNode) {
        parentNode.insertBefore(newNode, referenceNode);
      }

      function removeChild(node, child) {
        node.removeChild(child);
      }

      function appendChild(node, child) {
        node.appendChild(child);
      }

      function parentNode(node) {
        return node.parentElement;
      }

      function nextSibling(node) {
        return node.nextSibling;
      }

      function tagName(node) {
        return node.tagName;
      }

      function setTextContent(node, text) {
        node.textContent = text;
      }

      module.exports = {
        createElement: createElement,
        createElementNS: createElementNS,
        createTextNode: createTextNode,
        appendChild: appendChild,
        removeChild: removeChild,
        insertBefore: insertBefore,
        parentNode: parentNode,
        nextSibling: nextSibling,
        tagName: tagName,
        setTextContent: setTextContent
      };
    }, {}], 2: [function (require, module, exports) {
      module.exports = {
        array: Array.isArray,
        primitive: function primitive(s) {
          return typeof s === 'string' || typeof s === 'number';
        }
      };
    }, {}], 3: [function (require, module, exports) {
      // jshint newcap: false
      /* global require, module, document, Node */
      'use strict';

      var VNode = require('./vnode');
      var is = require('./is');
      var domApi = require('./htmldomapi');

      function isUndef(s) {
        return s === undefined;
      }
      function isDef(s) {
        return s !== undefined;
      }

      var emptyNode = VNode('', {}, [], undefined, undefined);

      function sameVnode(vnode1, vnode2) {
        return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
      }

      function createKeyToOldIdx(children, beginIdx, endIdx) {
        var i,
            map = {},
            key;
        for (i = beginIdx; i <= endIdx; ++i) {
          key = children[i].key;
          if (isDef(key)) map[key] = i;
        }
        return map;
      }

      var hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post'];

      function init(modules, api) {
        var i,
            j,
            cbs = {};

        if (isUndef(api)) api = domApi;

        for (i = 0; i < hooks.length; ++i) {
          cbs[hooks[i]] = [];
          for (j = 0; j < modules.length; ++j) {
            if (modules[j][hooks[i]] !== undefined) cbs[hooks[i]].push(modules[j][hooks[i]]);
          }
        }

        function emptyNodeAt(elm) {
          return VNode(api.tagName(elm).toLowerCase(), {}, [], undefined, elm);
        }

        function createRmCb(childElm, listeners) {
          return function () {
            if (--listeners === 0) {
              var parent = api.parentNode(childElm);
              api.removeChild(parent, childElm);
            }
          };
        }

        function createElm(vnode, insertedVnodeQueue) {
          var i,
              data = vnode.data;
          if (isDef(data)) {
            if (isDef(i = data.hook) && isDef(i = i.init)) {
              i(vnode);
              data = vnode.data;
            }
          }
          var elm,
              children = vnode.children,
              sel = vnode.sel;
          if (isDef(sel)) {
            // Parse selector
            var hashIdx = sel.indexOf('#');
            var dotIdx = sel.indexOf('.', hashIdx);
            var hash = hashIdx > 0 ? hashIdx : sel.length;
            var dot = dotIdx > 0 ? dotIdx : sel.length;
            var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
            elm = vnode.elm = isDef(data) && isDef(i = data.ns) ? api.createElementNS(i, tag) : api.createElement(tag);
            if (hash < dot) elm.id = sel.slice(hash + 1, dot);
            if (dotIdx > 0) elm.className = sel.slice(dot + 1).replace(/\./g, ' ');
            if (is.array(children)) {
              for (i = 0; i < children.length; ++i) {
                api.appendChild(elm, createElm(children[i], insertedVnodeQueue));
              }
            } else if (is.primitive(vnode.text)) {
              api.appendChild(elm, api.createTextNode(vnode.text));
            }
            for (i = 0; i < cbs.create.length; ++i) {
              cbs.create[i](emptyNode, vnode);
            }i = vnode.data.hook; // Reuse variable
            if (isDef(i)) {
              if (i.create) i.create(emptyNode, vnode);
              if (i.insert) insertedVnodeQueue.push(vnode);
            }
          } else {
            elm = vnode.elm = api.createTextNode(vnode.text);
          }
          return vnode.elm;
        }

        function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {
          for (; startIdx <= endIdx; ++startIdx) {
            api.insertBefore(parentElm, createElm(vnodes[startIdx], insertedVnodeQueue), before);
          }
        }

        function invokeDestroyHook(vnode) {
          var i,
              j,
              data = vnode.data;
          if (isDef(data)) {
            if (isDef(i = data.hook) && isDef(i = i.destroy)) i(vnode);
            for (i = 0; i < cbs.destroy.length; ++i) {
              cbs.destroy[i](vnode);
            }if (isDef(i = vnode.children)) {
              for (j = 0; j < vnode.children.length; ++j) {
                invokeDestroyHook(vnode.children[j]);
              }
            }
          }
        }

        function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
          for (; startIdx <= endIdx; ++startIdx) {
            var i,
                listeners,
                rm,
                ch = vnodes[startIdx];
            if (isDef(ch)) {
              if (isDef(ch.sel)) {
                invokeDestroyHook(ch);
                listeners = cbs.remove.length + 1;
                rm = createRmCb(ch.elm, listeners);
                for (i = 0; i < cbs.remove.length; ++i) {
                  cbs.remove[i](ch, rm);
                }if (isDef(i = ch.data) && isDef(i = i.hook) && isDef(i = i.remove)) {
                  i(ch, rm);
                } else {
                  rm();
                }
              } else {
                // Text node
                api.removeChild(parentElm, ch.elm);
              }
            }
          }
        }

        function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {
          var oldStartIdx = 0,
              newStartIdx = 0;
          var oldEndIdx = oldCh.length - 1;
          var oldStartVnode = oldCh[0];
          var oldEndVnode = oldCh[oldEndIdx];
          var newEndIdx = newCh.length - 1;
          var newStartVnode = newCh[0];
          var newEndVnode = newCh[newEndIdx];
          var oldKeyToIdx, idxInOld, elmToMove, before;

          while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
            if (isUndef(oldStartVnode)) {
              oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left
            } else if (isUndef(oldEndVnode)) {
              oldEndVnode = oldCh[--oldEndIdx];
            } else if (sameVnode(oldStartVnode, newStartVnode)) {
              patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);
              oldStartVnode = oldCh[++oldStartIdx];
              newStartVnode = newCh[++newStartIdx];
            } else if (sameVnode(oldEndVnode, newEndVnode)) {
              patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);
              oldEndVnode = oldCh[--oldEndIdx];
              newEndVnode = newCh[--newEndIdx];
            } else if (sameVnode(oldStartVnode, newEndVnode)) {
              // Vnode moved right
              patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);
              api.insertBefore(parentElm, oldStartVnode.elm, api.nextSibling(oldEndVnode.elm));
              oldStartVnode = oldCh[++oldStartIdx];
              newEndVnode = newCh[--newEndIdx];
            } else if (sameVnode(oldEndVnode, newStartVnode)) {
              // Vnode moved left
              patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);
              api.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);
              oldEndVnode = oldCh[--oldEndIdx];
              newStartVnode = newCh[++newStartIdx];
            } else {
              if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
              idxInOld = oldKeyToIdx[newStartVnode.key];
              if (isUndef(idxInOld)) {
                // New element
                api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
                newStartVnode = newCh[++newStartIdx];
              } else {
                elmToMove = oldCh[idxInOld];
                patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);
                oldCh[idxInOld] = undefined;
                api.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);
                newStartVnode = newCh[++newStartIdx];
              }
            }
          }
          if (oldStartIdx > oldEndIdx) {
            before = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;
            addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
          } else if (newStartIdx > newEndIdx) {
            removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
          }
        }

        function patchVnode(oldVnode, vnode, insertedVnodeQueue) {
          var i, hook;
          if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {
            i(oldVnode, vnode);
          }
          var elm = vnode.elm = oldVnode.elm,
              oldCh = oldVnode.children,
              ch = vnode.children;
          if (oldVnode === vnode) return;
          if (!sameVnode(oldVnode, vnode)) {
            var parentElm = api.parentNode(oldVnode.elm);
            elm = createElm(vnode, insertedVnodeQueue);
            api.insertBefore(parentElm, elm, oldVnode.elm);
            removeVnodes(parentElm, [oldVnode], 0, 0);
            return;
          }
          if (isDef(vnode.data)) {
            for (i = 0; i < cbs.update.length; ++i) {
              cbs.update[i](oldVnode, vnode);
            }i = vnode.data.hook;
            if (isDef(i) && isDef(i = i.update)) i(oldVnode, vnode);
          }
          if (isUndef(vnode.text)) {
            if (isDef(oldCh) && isDef(ch)) {
              if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue);
            } else if (isDef(ch)) {
              if (isDef(oldVnode.text)) api.setTextContent(elm, '');
              addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
            } else if (isDef(oldCh)) {
              removeVnodes(elm, oldCh, 0, oldCh.length - 1);
            } else if (isDef(oldVnode.text)) {
              api.setTextContent(elm, '');
            }
          } else if (oldVnode.text !== vnode.text) {
            api.setTextContent(elm, vnode.text);
          }
          if (isDef(hook) && isDef(i = hook.postpatch)) {
            i(oldVnode, vnode);
          }
        }

        return function (oldVnode, vnode) {
          var i, elm, parent;
          var insertedVnodeQueue = [];
          for (i = 0; i < cbs.pre.length; ++i) {
            cbs.pre[i]();
          }if (isUndef(oldVnode.sel)) {
            oldVnode = emptyNodeAt(oldVnode);
          }

          if (sameVnode(oldVnode, vnode)) {
            patchVnode(oldVnode, vnode, insertedVnodeQueue);
          } else {
            elm = oldVnode.elm;
            parent = api.parentNode(elm);

            createElm(vnode, insertedVnodeQueue);

            if (parent !== null) {
              api.insertBefore(parent, vnode.elm, api.nextSibling(elm));
              removeVnodes(parent, [oldVnode], 0, 0);
            }
          }

          for (i = 0; i < insertedVnodeQueue.length; ++i) {
            insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);
          }
          for (i = 0; i < cbs.post.length; ++i) {
            cbs.post[i]();
          }return vnode;
        };
      }

      module.exports = { init: init };
    }, { "./htmldomapi": 1, "./is": 2, "./vnode": 4 }], 4: [function (require, module, exports) {
      module.exports = function (sel, data, children, text, elm) {
        var key = data === undefined ? undefined : data.key;
        return { sel: sel, data: data, children: children,
          text: text, elm: elm, key: key };
      };
    }, {}] }, {}, [3])(3);
});