HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/helder.komma.pro/wwwroot/js/kms/core.js
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

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

/**
 * Event semi polyfill. IE does not support new event. But does support document.createEvent.
 * Same thing for dispatching events. But then with createEvent and fireEvent.
 */
function createNewEvent(eventName) {
  var event;

  if (typeof Event === 'function') {
    //On ie it is typeOf object.
    event = new Event(eventName); //Non-ie
  } else {
    event = document.createEvent('Event'); //ie

    event.initEvent(eventName, true, true);
  }

  return event;
}

function dispatchEventForElement(element, event) {
  if (document.createEvent) {
    element.dispatchEvent(event);
  } else {
    element.fireEvent("on" + event.eventType, event);
  }
}

Number.isInteger = Number.isInteger || function (value) {
  return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
};

(function (global, factory) {
  (typeof exports === "undefined" ? "undefined" : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : factory();
})(this, function () {
  'use strict';
  /**
   * @this {Promise}
   */

  function finallyConstructor(callback) {
    var constructor = this.constructor;
    return this.then(function (value) {
      return constructor.resolve(callback()).then(function () {
        return value;
      });
    }, function (reason) {
      return constructor.resolve(callback()).then(function () {
        return constructor.reject(reason);
      });
    });
  } // Store setTimeout reference so promise-polyfill will be unaffected by
  // other code modifying setTimeout (like sinon.useFakeTimers())


  var setTimeoutFunc = setTimeout;

  function noop() {} // Polyfill for Function.prototype.bind


  function bind(fn, thisArg) {
    return function () {
      fn.apply(thisArg, arguments);
    };
  }
  /**
   * @constructor
   * @param {Function} fn
   */


  function Promise(fn) {
    if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new');
    if (typeof fn !== 'function') throw new TypeError('not a function');
    /** @type {!number} */

    this._state = 0;
    /** @type {!boolean} */

    this._handled = false;
    /** @type {Promise|undefined} */

    this._value = undefined;
    /** @type {!Array<!Function>} */

    this._deferreds = [];
    doResolve(fn, this);
  }

  function handle(self, deferred) {
    while (self._state === 3) {
      self = self._value;
    }

    if (self._state === 0) {
      self._deferreds.push(deferred);

      return;
    }

    self._handled = true;

    Promise._immediateFn(function () {
      var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;

      if (cb === null) {
        (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
        return;
      }

      var ret;

      try {
        ret = cb(self._value);
      } catch (e) {
        reject(deferred.promise, e);
        return;
      }

      resolve(deferred.promise, ret);
    });
  }

  function resolve(self, newValue) {
    try {
      // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
      if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');

      if (newValue && (_typeof(newValue) === 'object' || typeof newValue === 'function')) {
        var then = newValue.then;

        if (newValue instanceof Promise) {
          self._state = 3;
          self._value = newValue;
          finale(self);
          return;
        } else if (typeof then === 'function') {
          doResolve(bind(then, newValue), self);
          return;
        }
      }

      self._state = 1;
      self._value = newValue;
      finale(self);
    } catch (e) {
      reject(self, e);
    }
  }

  function reject(self, newValue) {
    self._state = 2;
    self._value = newValue;
    finale(self);
  }

  function finale(self) {
    if (self._state === 2 && self._deferreds.length === 0) {
      Promise._immediateFn(function () {
        if (!self._handled) {
          Promise._unhandledRejectionFn(self._value);
        }
      });
    }

    for (var i = 0, len = self._deferreds.length; i < len; i++) {
      handle(self, self._deferreds[i]);
    }

    self._deferreds = null;
  }
  /**
   * @constructor
   */


  function Handler(onFulfilled, onRejected, promise) {
    this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
    this.onRejected = typeof onRejected === 'function' ? onRejected : null;
    this.promise = promise;
  }
  /**
   * Take a potentially misbehaving resolver function and make sure
   * onFulfilled and onRejected are only called once.
   *
   * Makes no guarantees about asynchrony.
   */


  function doResolve(fn, self) {
    var done = false;

    try {
      fn(function (value) {
        if (done) return;
        done = true;
        resolve(self, value);
      }, function (reason) {
        if (done) return;
        done = true;
        reject(self, reason);
      });
    } catch (ex) {
      if (done) return;
      done = true;
      reject(self, ex);
    }
  }

  Promise.prototype['catch'] = function (onRejected) {
    return this.then(null, onRejected);
  };

  Promise.prototype.then = function (onFulfilled, onRejected) {
    // @ts-ignore
    var prom = new this.constructor(noop);
    handle(this, new Handler(onFulfilled, onRejected, prom));
    return prom;
  };

  Promise.prototype['finally'] = finallyConstructor;

  Promise.all = function (arr) {
    return new Promise(function (resolve, reject) {
      if (!arr || typeof arr.length === 'undefined') throw new TypeError('Promise.all accepts an array');
      var args = Array.prototype.slice.call(arr);
      if (args.length === 0) return resolve([]);
      var remaining = args.length;

      function res(i, val) {
        try {
          if (val && (_typeof(val) === 'object' || typeof val === 'function')) {
            var then = val.then;

            if (typeof then === 'function') {
              then.call(val, function (val) {
                res(i, val);
              }, reject);
              return;
            }
          }

          args[i] = val;

          if (--remaining === 0) {
            resolve(args);
          }
        } catch (ex) {
          reject(ex);
        }
      }

      for (var i = 0; i < args.length; i++) {
        res(i, args[i]);
      }
    });
  };

  Promise.resolve = function (value) {
    if (value && _typeof(value) === 'object' && value.constructor === Promise) {
      return value;
    }

    return new Promise(function (resolve) {
      resolve(value);
    });
  };

  Promise.reject = function (value) {
    return new Promise(function (resolve, reject) {
      reject(value);
    });
  };

  Promise.race = function (values) {
    return new Promise(function (resolve, reject) {
      for (var i = 0, len = values.length; i < len; i++) {
        values[i].then(resolve, reject);
      }
    });
  }; // Use polyfill for setImmediate for performance gains


  Promise._immediateFn = typeof setImmediate === 'function' && function (fn) {
    setImmediate(fn);
  } || function (fn) {
    setTimeoutFunc(fn, 0);
  };

  Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
    if (typeof console !== 'undefined' && console) {
      console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
    }
  };
  /** @suppress {undefinedVars} */


  var globalNS = function () {
    // the only reliable means to get the global object is
    // `Function('return this')()`
    // However, this causes CSP violations in Chrome apps.
    if (typeof self !== 'undefined') {
      return self;
    }

    if (typeof window !== 'undefined') {
      return window;
    }

    if (typeof global !== 'undefined') {
      return global;
    }

    throw new Error('unable to locate global object');
  }();

  if (!('Promise' in globalNS)) {
    globalNS['Promise'] = Promise;
  } else if (!globalNS.Promise.prototype['finally']) {
    globalNS.Promise.prototype['finally'] = finallyConstructor;
  }
});

!function (global, factory) {
  "use strict";

  "object" == (typeof module === "undefined" ? "undefined" : _typeof(module)) && "object" == _typeof(module.exports) ? module.exports = factory(global) : factory(global);
}("undefined" != typeof window ? window : global, function (global) {
  "use strict";

  var defineProperty = Object.defineProperty,
      defineProperties = Object.defineProperties,
      symbolHiddenCounter = 0,
      globalSymbolRegistry = [],
      slice = Array.prototype.slice,
      ES6 = "object" == _typeof(global.ES6) ? global.ES6 : global.ES6 = {},
      isArray = Array.isArray,
      objectToString = Object.prototype.toString,
      push = Array.prototype.push,
      emptyFunction = function emptyFunction() {},
      simpleFunction = function simpleFunction(arg) {
    return arg;
  },
      isCallable = function isCallable(fn) {
    return "function" == typeof fn;
  },
      Iterator = function Iterator() {},
      ArrayIterator = function ArrayIterator(array, flag) {
    this._array = array, this._flag = flag, this._nextIndex = 0;
  },
      StringIterator = function StringIterator(string, flag) {
    this._string = string, this._flag = flag, this._nextIndex = 0;
  },
      isObject = function isObject(value) {
    return null !== value && ("object" == _typeof(value) || "function" == typeof value);
  },
      setupSymbolInternals = function setupSymbolInternals(symbol, desc) {
    return defineProperties(symbol, {
      _description: {
        value: desc
      },
      _isSymbol: {
        value: !0
      },
      _id: {
        value: symbolHiddenCounter++
      }
    }), symbol;
  },
      appendArray = function appendArray(array1, array2) {
    if ("number" == typeof array1.length && array1.length >= 0 && "number" == typeof array2.length && array2.length >= 0) {
      var length1 = Math.floor(array1.length),
          length2 = Math.floor(array2.length),
          i = 0;

      for (array1.length = length1 + length2; i < length2; ++i) {
        array2.hasOwnProperty(i) && (array1[length1 + i] = array2[i]);
      }
    }
  },
      simpleInheritance = function simpleInheritance(child, parent) {
    if ("function" != typeof child || "function" != typeof parent) throw new TypeError("Child and Parent must be function type");
    child.prototype = Object.create(parent.prototype), child.prototype.constructor = child;
  },
      _Symbol = function _Symbol2(desc) {
    if (desc = void 0 === desc ? "" : String(desc), this instanceof _Symbol2) throw new TypeError("Symbol is not a constructor");
    return setupSymbolInternals(Object.create(_Symbol2.prototype), desc);
  };

  defineProperties(_Symbol, {
    for: {
      value: function value(key) {
        key = String(key);

        for (var record, registryLength = globalSymbolRegistry.length, i = 0; i < registryLength; ++i) {
          if ((record = globalSymbolRegistry[i]).key === key) return record.symbol;
        }

        return record = {
          key: key,
          symbol: _Symbol(key)
        }, globalSymbolRegistry.push(record), record.symbol;
      },
      writable: !0,
      configurable: !0
    },
    keyFor: {
      value: function value(symbol) {
        if (!ES6.isSymbol(symbol)) throw new TypeError(String(symbol) + " is not a symbol");

        for (var record, registryLength = globalSymbolRegistry.length, i = 0; i < registryLength; ++i) {
          if ((record = globalSymbolRegistry[i]).symbol === symbol) return record.key;
        }
      },
      writable: !0,
      configurable: !0
    },
    hasInstance: {
      value: _Symbol("Symbol.hasInstance")
    },
    isConcatSpreadable: {
      value: _Symbol("Symbol.isConcatSpreadable")
    },
    iterator: {
      value: _Symbol("Symbol.iterator")
    },
    toStringTag: {
      value: _Symbol("Symbol.toStringTag")
    }
  }), _Symbol.prototype.toString = function () {
    return "@@_____" + this._id + "_____";
  }, _Symbol.prototype.valueOf = function () {
    return this;
  }, defineProperty(Iterator.prototype, _Symbol.iterator.toString(), {
    value: function value() {
      return this;
    },
    writable: !0,
    configurable: !0
  }), simpleInheritance(ArrayIterator, Iterator), simpleInheritance(StringIterator, Iterator), defineProperty(ArrayIterator.prototype, _Symbol.toStringTag.toString(), {
    value: "Array Iterator",
    configurable: !0
  }), defineProperty(StringIterator.prototype, _Symbol.toStringTag.toString(), {
    value: "String Iterator",
    configurable: !0
  }), ArrayIterator.prototype.next = function () {
    if (!(this instanceof ArrayIterator)) throw new TypeError("Method Array Iterator.prototype.next called on incompatible receiver " + String(this));
    var nextValue;
    return -1 === this._nextIndex ? {
      done: !0,
      value: void 0
    } : "number" == typeof this._array.length && this._array.length >= 0 && this._nextIndex < Math.floor(this._array.length) ? (1 === this._flag ? nextValue = [this._nextIndex, this._array[this._nextIndex]] : 2 === this._flag ? nextValue = this._array[this._nextIndex] : 3 === this._flag && (nextValue = this._nextIndex), this._nextIndex++, {
      done: !1,
      value: nextValue
    }) : (this._nextIndex = -1, {
      done: !0,
      value: void 0
    });
  }, StringIterator.prototype.next = function () {
    if (!(this instanceof StringIterator)) throw new TypeError("Method String Iterator.prototype.next called on incompatible receiver " + String(this));
    var nextValue,
        stringObject = new String(this._string);
    return -1 === this._nextIndex ? {
      done: !0,
      value: void 0
    } : this._nextIndex < stringObject.length ? (nextValue = stringObject[this._nextIndex], this._nextIndex++, {
      done: !1,
      value: nextValue
    }) : (this._nextIndex = -1, {
      done: !0,
      value: void 0
    });
  };

  var SpreadOperatorImpl = function SpreadOperatorImpl(target, thisArg) {
    this._target = target, this._values = [], this._thisArg = thisArg;
  };

  SpreadOperatorImpl.prototype.spread = function () {
    var self = this;
    return slice.call(arguments).forEach(function (iterable) {
      ES6.forOf(iterable, function (value) {
        self._values.push(value);
      });
    }), self;
  }, SpreadOperatorImpl.prototype.add = function () {
    var self = this;
    return slice.call(arguments).forEach(function (value) {
      self._values.push(value);
    }), self;
  }, SpreadOperatorImpl.prototype.call = function (thisArg) {
    if ("function" != typeof this._target) throw new TypeError("Target is not a function");
    return thisArg = arguments.length <= 0 ? this._thisArg : thisArg, this._target.apply(thisArg, this._values);
  }, SpreadOperatorImpl.prototype.new = function () {
    if ("function" != typeof this._target) throw new TypeError("Target is not a constructor");
    var temp, returnValue;
    return temp = Object.create(this._target.prototype), returnValue = this._target.apply(temp, this._values), isObject(returnValue) ? returnValue : temp;
  }, SpreadOperatorImpl.prototype.array = function () {
    if (!isArray(this._target)) throw new TypeError("Target is not a array");
    return push.apply(this._target, this._values), this._target;
  };
  return defineProperties(ES6, {
    isSymbol: {
      value: function value(symbol) {
        return symbol instanceof _Symbol && function (symbol) {
          return !0 === symbol._isSymbol && "number" == typeof symbol._id && "string" == typeof symbol._description;
        }(symbol);
      },
      writable: !0,
      configurable: !0
    },
    instanceOf: {
      value: function value(object, constructor) {
        if (!isObject(constructor)) throw new TypeError("Right-hand side of 'instanceof' is not an object");
        var hasInstanceSymbolProp = constructor[_Symbol.hasInstance];
        if (void 0 === hasInstanceSymbolProp) return object instanceof constructor;
        if ("function" != typeof hasInstanceSymbolProp) throw new TypeError(_typeof(hasInstanceSymbolProp) + " is not a function");
        return hasInstanceSymbolProp.call(constructor, object);
      },
      writable: !0,
      configurable: !0
    },
    forOf: {
      value: function value(iterable, callback, thisArg) {
        if (callback = "function" != typeof callback ? emptyFunction : callback, "function" != typeof iterable[_Symbol.iterator]) throw new TypeError("Iterable[Symbol.iterator] is not a function");

        var iterationResult,
            iterator = iterable[_Symbol.iterator]();

        if ("function" != typeof iterator.next) throw new TypeError(".iterator.next is not a function");

        for (;;) {
          if (iterationResult = iterator.next(), !isObject(iterationResult)) throw new TypeError("Iterator result " + iterationResult + " is not an object");
          if (iterationResult.done) break;
          callback.call(thisArg, iterationResult.value);
        }
      },
      writable: !0,
      configurable: !0
    },
    spreadOperator: {
      value: function value(target, thisArg) {
        if ("function" != typeof target && !isArray(target)) throw new TypeError("Spread operator only supports on array and function objects at this moment");
        return new SpreadOperatorImpl(target, thisArg);
      },
      writable: !0,
      configurable: !0
    }
  }), defineProperty(global, "Symbol", {
    value: _Symbol,
    writable: !0,
    configurable: !0
  }), defineProperty(Function.prototype, _Symbol.hasInstance.toString(), {
    value: function value(instance) {
      return "function" == typeof this && instance instanceof this;
    }
  }), defineProperty(Array.prototype, "concat", {
    value: function value() {
      if (void 0 === this || null === this) throw new TypeError("Array.prototype.concat called on null or undefined");
      var self = Object(this),
          targets = slice.call(arguments),
          outputs = [];
      return targets.unshift(self), targets.forEach(function (target) {
        isObject(target) ? void 0 !== target[_Symbol.isConcatSpreadable] ? target[_Symbol.isConcatSpreadable] ? appendArray(outputs, target) : outputs.push(target) : isArray(target) ? appendArray(outputs, target) : outputs.push(target) : outputs.push(target);
      }), outputs;
    },
    writable: !0,
    configurable: !0
  }), defineProperty(Object.prototype, "toString", {
    value: function value() {
      return void 0 === this || null === this ? objectToString.call(this) : "string" == typeof this[_Symbol.toStringTag] ? "[object " + this[_Symbol.toStringTag] + "]" : objectToString.call(this);
    },
    writable: !0,
    configurable: !0
  }), defineProperty(Array.prototype, _Symbol.iterator.toString(), {
    value: function value() {
      if (void 0 === this || null === this) throw new TypeError("Cannot convert undefined or null to object");
      var self = Object(this);
      return new ArrayIterator(self, 2);
    },
    writable: !0,
    configurable: !0
  }), defineProperty(Array, "from", {
    value: function value(arrayLike, mapFn, thisArg) {
      var constructor,
          length,
          outputs,
          i = 0;
      if (constructor = isCallable(this) ? this : Array, void 0 === arrayLike || null === arrayLike) throw new TypeError("Cannot convert undefined or null to object");
      if (arrayLike = Object(arrayLike), void 0 === mapFn) mapFn = simpleFunction;else if (!isCallable(mapFn)) throw new TypeError(mapFn + " is not a function");

      if (void 0 === arrayLike[_Symbol.iterator]) {
        if (!("number" == typeof arrayLike.length && arrayLike.length >= 0)) return (outputs = new constructor(0)).length = 0, outputs;

        for (length = Math.floor(arrayLike.length), (outputs = new constructor(length)).length = length; i < length; ++i) {
          outputs[i] = mapFn.call(thisArg, arrayLike[i]);
        }
      } else (outputs = new constructor()).length = 0, ES6.forOf(arrayLike, function (value) {
        outputs.length++, outputs[outputs.length - 1] = mapFn.call(thisArg, value);
      });

      return outputs;
    },
    writable: !0,
    configurable: !0
  }), defineProperty(Array.prototype, "entries", {
    value: function value() {
      if (void 0 === this || null === this) throw new TypeError("Cannot convert undefined or null to object");
      var self = Object(this);
      return new ArrayIterator(self, 1);
    },
    writable: !0,
    configurable: !0
  }), defineProperty(Array.prototype, "keys", {
    value: function value() {
      if (void 0 === this || null === this) throw new TypeError("Cannot convert undefined or null to object");
      var self = Object(this);
      return new ArrayIterator(self, 3);
    },
    writable: !0,
    configurable: !0
  }), defineProperty(String.prototype, _Symbol.iterator.toString(), {
    value: function value() {
      if (void 0 === this || null === this) throw new TypeError("String.prototype[Symbol.iterator] called on null or undefined");
      return new StringIterator(String(this), 0);
    },
    writable: !0,
    configurable: !0
  }), ES6;
});
/* ==========================================================================
    Helper functions
 ========================================================================== */

/*
 * Simple isset method for this does not exist in javascript
 */

var isset = function isset(obj) {
  return typeof obj !== 'undefined' && obj !== null;
};
/*
 * Easing Functions - inspired from http://gizma.com/easing/
 * only considering the t value for the range [0, 1] => [0, 1]
 */


var EasingFunctions = {
  // no easing, no acceleration
  linear: function linear(t) {
    return t;
  },
  // accelerating from zero velocity
  easeInQuad: function easeInQuad(t) {
    return t * t;
  },
  // decelerating to zero velocity
  easeOutQuad: function easeOutQuad(t) {
    return t * (2 - t);
  },
  // acceleration until halfway, then deceleration
  easeInOutQuad: function easeInOutQuad(t) {
    return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
  },
  // accelerating from zero velocity
  easeInCubic: function easeInCubic(t) {
    return t * t * t;
  },
  // decelerating to zero velocity
  easeOutCubic: function easeOutCubic(t) {
    return --t * t * t + 1;
  },
  // acceleration until halfway, then deceleration
  easeInOutCubic: function easeInOutCubic(t) {
    return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
  },
  // accelerating from zero velocity
  easeInQuart: function easeInQuart(t) {
    return t * t * t * t;
  },
  // decelerating to zero velocity
  easeOutQuart: function easeOutQuart(t) {
    return 1 - --t * t * t * t;
  },
  // acceleration until halfway, then deceleration
  easeInOutQuart: function easeInOutQuart(t) {
    return t < .5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
  },
  // accelerating from zero velocity
  easeInQuint: function easeInQuint(t) {
    return t * t * t * t * t;
  },
  // decelerating to zero velocity
  easeOutQuint: function easeOutQuint(t) {
    return 1 + --t * t * t * t * t;
  },
  // acceleration until halfway, then deceleration
  easeInOutQuint: function easeInOutQuint(t) {
    return t < .5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
  }
};
/*
 * Vanilla version of the $.getScript
 */

var getScript = function getScript(source, callback) {
  var script = document.createElement('script');
  script.async = 1;
  var scripts = document.getElementsByTagName('script');
  var prior = scripts[scripts.length - 1];

  script.onload = script.onreadystatechange = function (_, isAbort) {
    if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
      script.onload = script.onreadystatechange = null;
      script = undefined;

      if (!isAbort) {
        if (callback) callback();
      }
    }
  };

  script.src = source;
  prior.parentNode.insertBefore(script, prior);
};
/**
 * Returns a function, that, as long as it continues to be invoked, will not
 * be triggered. The function will be called after it stops being called for
 * N milliseconds. If `immediate` is passed, trigger the function on the
 * leading edge, instead of the trailing.
 * @param func
 * @param wait
 * @param immediate
 * @returns {Function}
 */


var debounce = function debounce(func, wait, immediate) {
  var timeout;
  return function () {
    var context = this,
        args = arguments;

    var later = function later() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };

    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};
/*
 * Cookie helper class
 */


var Cookie = {
  set: function set(name, value, days) {
    var domain, domainParts, date, expires, host;

    if (days) {
      date = new Date();
      date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
      expires = "; expires=" + date.toGMTString();
    } else {
      expires = "";
    }

    host = location.host;

    if (host.split('.').length === 1) {
      // no "." in a domain - it's localhost or something similar
      document.cookie = name + "=" + value + expires + "; path=/";
    } else {
      // Remember the cookie on all sub domains.
      //
      // Start with trying to set cookie to the top domain.
      // (example: if user is on foo.com, try to set
      //  cookie to domain ".com")
      //
      // If the cookie will not be set, it means ".com"
      // is a top level domain and we need to
      // set the cookie to ".foo.com"
      domainParts = host.split('.');
      domainParts.shift();
      domain = '.' + domainParts.join('.'); // For development purpose, remove this when moving to production

      domain = '.komma.pro';
      document.cookie = name + "=" + value + expires + "; path=/; domain=" + domain; // check if cookie was successfuly set to the given domain
      // (otherwise it was a Top-Level Domain)

      if (Cookie.get(name) == null || Cookie.get(name) != value) {
        // append "." to current domain
        domain = '.' + host;
        document.cookie = name + "=" + value + expires + "; path=/; domain=" + domain;
      }
    }
  },
  get: function get(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');

    for (var i = 0; i < ca.length; i++) {
      var c = ca[i];

      while (c.charAt(0) === ' ') {
        c = c.substring(1, c.length);
      }

      if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
    }

    return null;
  },
  erase: function erase(name) {
    Cookie.set(name, '', -1);
  }
};
/*
 * Javascript version of the number_format method of PHP
 */

var number_format = function number_format(number, decimals, dec_point, thousands_sep) {
  // Strip all characters but numerical ones.
  number = (number + '').replace(/[^0-9+\-Ee.]/g, '');

  var n = !isFinite(+number) ? 0 : +number,
      prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
      sep = typeof thousands_sep === 'undefined' ? ',' : thousands_sep,
      dec = typeof dec_point === 'undefined' ? '.' : dec_point,
      s = '',
      toFixedFix = function toFixedFix(n, prec) {
    var k = Math.pow(10, prec);
    return '' + Math.round(n * k) / k;
  }; // Fix for IE parseFloat(0.55).toFixed(0) = 0;


  s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');

  if (s[0].length > 3) {
    s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
  }

  if ((s[1] || '').length < prec) {
    s[1] = s[1] || '';
    s[1] += new Array(prec - s[1].length + 1).join('0');
  }

  return s.join(dec);
};

var Ajax = {
  get: function get(url, callback) {},
  post: function post(url, data, callback) {
    var xhr = new XMLHttpRequest();
    var token = document.querySelector('meta[name="csrf-token"]').content;
    xhr.open('post', url, true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.setRequestHeader('X-CSRF-TOKEN', token);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          callback(xhr);
        } else {
          console.error('ShoppingCart: Could not add product because of an error. ' + xhr.statusText);
        }
      }
    };

    xhr.send(JSON.stringify(data));
  }
};
'use strict';

document.addEventListener('DOMContentLoaded', function () {
  //Make the tabs work
  new TabsController('tab-content', 'entity-tabs', 'active', true, 'input[name="tabslug"]'); //Add a style manager for the visible save button
  //enable save button when present add add a

  var visibleSaveButton = document.getElementById('save-button');
  var saveButtonStyleController = new styleClassController(visibleSaveButton);

  if (visibleSaveButton) {
    var realSaveButton = document.querySelector('input[value="submit-cloaked"]');
    visibleSaveButton.addEventListener('click', function (visibleSaveButtonClickEvent) {
      visibleSaveButtonClickEvent.preventDefault();
      saveButtonStyleController.requestAddClass('disabled');
      realSaveButton.click();
    });
  } //Make the trash button only work when it is confirmed by a model


  var trashButton = document.querySelector('input.trash.confirm');
  if (trashButton) new ConfirmationController(trashButton); //Get the form and its translations

  var form = document.getElementById('entity-form');
  var globalTranslations = form ? form.dataset.globalTranslations : {}; //Create an entityInitializer that will look inside of the selected element and when something changes in it, triggers callbacks if needed

  var entityInitializer = new Initializer('#entity-form'); //Make sure all component areas will be initialized when they show up

  entityInitializer.bindSelectorToCallback('.js-components-area', function (attributesInitializer, componentAreaAttributeElement) {
    var componentAreaManager = new ComponentAreaManager(componentAreaAttributeElement, new ComponentManagerApiController());
  }); //Make sure all documents attributes are initialized when they show up.

  entityInitializer.bindSelectorToCallback('.entity-attribute-documents', function (attributesInitializer, documentsGroupAttributeElement) {
    var uploadRoute = form.dataset.uploadRoute;
    var maxPostSize = form.dataset.maxPostSize;
    var maxUploadSize = form.dataset.maxUploadSize;
    var html5Uploader = new HTML5Uploader(uploadRoute, maxPostSize, maxUploadSize, globalTranslations);
    var documentManager = new DocumentManager(documentsGroupAttributeElement, html5Uploader);
    new FileDragAndDropHandler(documentsGroupAttributeElement.querySelector('.drag-and-drop-area')).hookTo(documentManager); //Enable or disable the save button depending on the uploads

    html5Uploader.on('uploadStart', function () {
      saveButtonStyleController.requestAddClass('disabled');
    });
    html5Uploader.on('uploadComplete', function () {
      saveButtonStyleController.requestRemoveClass('disabled');
    });
    html5Uploader.on('uploadCanceled', function () {
      saveButtonStyleController.requestRemoveClass('disabled');
    });
    html5Uploader.on('uploadFailed', function () {
      saveButtonStyleController.requestRemoveClass('disabled');
    });
  });
  entityInitializer.bindSelectorToCallback('.entity-attribute-multiselect-combo-box', function (attributesInitializer, multiselectComboBoxAttributeElement) {
    if (multiselectComboBoxAttributeElement.dataset.readonly === 'false') {
      var multiSelect = new MultiSelect(multiselectComboBoxAttributeElement);
    }
  });
  entityInitializer.bindSelectorToCallback('.entity-attribute-on-off', function (attributesInitializer, onOffAttributeElement) {
    var onOff = new OnOff(onOffAttributeElement);
  });
  entityInitializer.bindSelectorToCallback('.js-video', function (attributesInitializer, videoAttributeElement) {
    var video = new Video(videoAttributeElement);
  }); //Make sure all confirmable things are initialized when they show up

  entityInitializer.bindSelectorToCallback('.confirm', function (attributesInitializer, confirmableHtmlElement) {
    new ConfirmationController(confirmableHtmlElement);
  });
  entityInitializer.bindSelectorToCallback('.entity-attribute-select', function (attributesInitializer, selectAttributeElement) {
    var select = new Select(selectAttributeElement);
  });
  entityInitializer.bindSelectorToCallback('[data-to-copy]', function (attributesInitializer, element) {
    console.log('found copy text element');
    new CopyText(element);
  }); //Make sure all tiny mce editors are initialized //TODO. needs fix

  entityInitializer.bindSelectorToCallback('.tiny-mce', function (attributesInitializer, inputElement) {
    if (!inputElement.id) inputElement.id = new Date().getTime() + Math.random().toString(36).substring(7); //Gives the element a random id if it does not have any. Makes it selectable by tinyMce's remove method.

    tinymce.remove('#' + inputElement.id); //Removes the previous tiny mce editor instance if any.

    tinymce.init({
      target: inputElement,
      skin: 'kms',
      menubar: false,
      statusbar: false,
      plugins: ['code', 'paste', 'link', 'table'],
      toolbar: 'styleselect | bold italic underline | bullist numlist  | indent | link image | table | code',
      height: '200',
      paste_as_text: false,
      style_formats: [{
        title: 'Titel 2',
        block: 'h2'
      }, {
        title: 'Titel 3',
        block: 'h3'
      }, {
        title: 'Hierarchy',
        block: 'div',
        classes: 'hierarchy'
      }],
      convert_urls: false,
      setup: function setup(editor) {
        editor.on('change', function (changeEvent) {
          updateOriginalInput(editor, inputElement);
        });
      }
    });

    function updateOriginalInput(tinyMceEditor, inputElement) {
      tinyMceEditor.save();
      var changeEvent = createNewEvent('change');
      dispatchEventForElement(inputElement, changeEvent);
    }
  }, false); //Start looking for changes in #entity-form. And if one occurs, check if it did include one of the bound selector.

  entityInitializer.startObserving();
  new PreventNavigationController(document.querySelector('.entity-attributes'));
});

(function ($) {
  // TinyMCE
  tinymce.init({
    selector: 'textarea.tiny-mce',
    skin: 'kms',
    menubar: false,
    statusbar: false,
    plugins: ['code', 'paste', 'link', 'table'],
    toolbar: 'styleselect | bold italic underline | bullist numlist  | indent | link image | table | code',
    height: '200',
    paste_as_text: true,
    style_formats: [{
      title: 'Titel 2',
      block: 'h2'
    }, {
      title: 'Titel 3',
      block: 'h3'
    }],
    convert_urls: false // link_list: "/kms/file-list?key=komma_kms",

  }); // Hierarchical list

  $('.entities-list-item .dropdown-icon').click(function (e) {
    e.preventDefault();

    if ($(this).parent().parent().hasClass('open')) {
      //$('.animate-to-triangle', this)[0].beginElement();
      $(this).parent().parent().removeClass('open');
    } else {
      //$('.animate-to-minus', this)[0].beginElement();
      $(this).parent().parent().addClass('open');
    }
  });
  var toggled = true; // Scroll to active item in list

  $(window).load(function () {
    if ($('#entity-form .lock').hasClass('open')) {
      toggled = false;
      $('#entity-form').find('input, textarea').attr('disabled', toggled);
    }

    var $container = $('#entities .entities-list');
    var $activeListItem = $('.entities-list-item.active', $container).first();
    if ($activeListItem.length == 0) return;
    var top = $activeListItem.position().top;
    $container.scrollTop(top);
    $('.site-brand-name input').attr('placeholder', $('#global_name').val());
  });
  $('#global_name').change(function () {
    $('.site-brand-name input').attr('placeholder', $(this).val());
  }); //error accordian

  $('.error-accordion .collapsible-ul').hide();
  $('.error-accordion h3').click(function () {
    $(this).parent().find('.collapsible-ul').toggle();
  }); //$('.order-status.selectize').selectize();
  // Product category selector
  //$('#productCategorySelector').selectize();
  //$('#selectYearAndMonthForm select').selectize();

  $('#selectYearAndMonthForm select').change(function () {
    var location = '/kms/orders/voltooid?month=' + $('#selectYearAndMonthForm select#orderMonthSelector').val() + '&year=' + $('#selectYearAndMonthForm select#orderYearSelector').val();
    window.location = location;
  });
  $('#productCategorySelector').change(function () {
    window.location = '/kms/products?category=' + encodeURIComponent(this.value);
  }); // Flash messages

  var hideFlashMessage = function hideFlashMessage() {
    $('#flash-message').fadeOut();
  };

  $('#flash-message').click(function () {
    hideFlashMessage();
  });
  setTimeout(function () {
    hideFlashMessage();
  }, 5000); //var toggled = true;

  $('#entity-form .lock').click(function () {
    $(this).toggleClass('open');
    toggled = !toggled;
    $(this).parents('#entity-form').find('input, textarea').attr('disabled', toggled);
  });
  /* grab important elements */

  var sortInput = jQuery('#sort_order');
  var submit = jQuery('#autoSubmit');
  var messageBox = jQuery('#message-box');
  var list = jQuery('.fieldGroupItems');
  /* create requesting function to avoid duplicate code */

  /* worker function */

  var fnSubmit = function fnSubmit(save) {
    var sortOrder = [];
    list.children('li').each(function () {
      sortOrder.push(jQuery(this).data('id'));
    });
    sortInput.val(sortOrder.join(','));
    console.log(sortInput.val());

    if (save) {
      request();
    }
  };
  /* store values */


  list.children('li').each(function () {
    var li = jQuery(this);
    li.data('id', li.attr('title')).attr('title', '');
  });
  /* sortables */

  list.sortable({
    opacity: 0.7,
    update: function update() {}
  });
  /* ajax form submission */

  jQuery('#dd-form').bind('submit', function (e) {
    if (e) e.preventDefault();
    fnSubmit(true);
  });
})(jQuery);

document.addEventListener('DOMContentLoaded', function () {
  var activeListItem = document.querySelector('#sidebar .navigation li.active'); //Make parent menu items (li with class has-sub-items) also active

  function makeParentListItemsActiveIfHasClassHasSubItems(liElement) {
    var parent = liElement.parentElement ? liElement.parentElement : liElement.parentNode; // Stupid IE11

    if (parent.classList.contains('has-sub-items') && parent.tagName === "LI") {
      parent.classList.add('active');
      makeParentListItemsActiveIfHasClassHasSubItems(parent);
    }
  }

  if (activeListItem) {
    makeParentListItemsActiveIfHasClassHasSubItems(activeListItem);
  } //Make site list items openable by toggling a class tot them when clicked


  var siteListItems = document.querySelectorAll('#sidebar .navigation .has-sub-items');
  var siteListItemsLength = siteListItems.length;

  for (var i = 0; i < siteListItemsLength; i++) {
    var siteListItem = siteListItems[i];
    siteListItem.addEventListener('click', function () {
      this.classList.toggle('active');
    });
  }
});
/**
 * Fills an ul element with data retrieved from an api and makes the items searchable.
 /* The data to and from the api has this structure for example.
 *
 * [
 *  {
 *      id:1
 *      title:false
 *      thumbnail:false
 *      status: "active"
 *      routes: []
 *      children: [
 *          {
 *              id: 12
 *              title: "Thuis"
 *              thumbnail: false
 *              routes: [{
 *                  40: "en/Homenew",
 *                  104: "nl/Thuisnew"
 *              }]
 *          }
 *      ]
 *  }
 * ]
 */

var SearchController =
/*#__PURE__*/
function () {
  function SearchController(sectionId, selector, inputSelector, mainUlId, resultCounterId) {
    _classCallCheck(this, SearchController);

    this.apiUrl = '';
    this.data = '';
    this.dataToLoad = '';
    this.editEntitiesUrl = '';
    this.initialized = false;
    this.sectionId = sectionId;
    this.selector = selector;
    this.mainUlId = mainUlId;
    this.resultCounterId = resultCounterId;
    this.disabled = true;
    this.inputSelector = inputSelector;
    this.listItemClass = 'entities-list-item'; //The class that is added to li items that must be visible because they match (a part) of the search value).
    //This is also the class applied to the rootUl if any results are found.

    this.visibleClass = 'active';
    this.invisibleClass = 'hide';
    this.section = document.getElementById(this.sectionId);
    var rootUl = document.querySelector(this.selector);
    this.siteSlug = rootUl.dataset.siteSlug;
    this.slug = rootUl.dataset.slug;
    this.activeId = rootUl.dataset.activeId;
    axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
  }
  /**
   * Initializes the controller so that it knows where it can get its data from,
   * where it needs to direct users when they click on an item and from which ul it
   * should create a sortable ul
   *
   * @param dataSource A string|Object
   * @param editEntitiesUrl A string
   *
   * In case of the data source being an object it must look like this:
   * {
   *  data: [{
   *      id: null,
   *      routes: []
   *      status: "",
   *      title: "",
   *      children: [
   *          {
   *              id: "2",
   *              routes: []
   *              status: "",
   *              title: "My username"
   *              children: []
   *          }
   *      ]
   *  }]
   * }
   */


  _createClass(SearchController, [{
    key: "init",
    value: function init(dataSource, editEntitiesUrl) {
      if (typeof dataSource === "string") {
        this.apiUrl = dataSource;
      } else {
        this.dataToLoad = dataSource;
      }

      this.editEntitiesUrl = editEntitiesUrl;
      this.initialized = true;
    }
    /**
     * Returns a promise that resolves with the root ul that then will contain the items retrieved from the api
     */

  }, {
    key: "load",
    value: function load() {
      if (this.initialized === false) {
        console.error('Please initialize the controller with the init method first.');
        return;
      }

      var self = this;
      return new Promise(function (resolve, reject) {
        if (self.initialized === false) {
          reject('Please initialize the controller with the init method first.');
        }

        if (self.apiUrl !== '' && self.dataToLoad === '') {
          axios.get(self.apiUrl).then(function (response) {
            if (!response.data || response.data.length == 0) {
              reject('The searchable did not get any data from the api');
              return;
            } // console.log(response);

            /** @var Array[] menuItemArrays*/


            var childrenLength = response.data.children.length;

            for (var i = 0; i < childrenLength; i++) {
              /** @var array htmlElements **/
              var htmlElements = self.createHtmlElement(response.data.children[i]);
              var htmlElementsLength = htmlElements.length;

              for (var j = 0; j < htmlElementsLength; j++) {
                document.querySelector(self.selector).appendChild(htmlElements[j]);
              }
            } // console.log(document.querySelector(self.selector));


            self.initializeSearch();
            resolve(document.querySelector(self.selector));
          }).catch(function (error) {
            reject(error);
          });
        } else if (self.apiUrl === '' && self.dataToLoad !== '') {
          // console.log('data children');
          // console.log(self.dataToLoad.data.children);

          /** @var Array[] menuItemArrays*/
          var childrenLength = self.dataToLoad.data.children.length;

          for (var i = 0; i < childrenLength; i++) {
            /** @var array htmlElements **/
            var htmlElements = self.createHtmlElement(self.dataToLoad.data.children[i]);
            var htmlElementsLength = htmlElements.length;

            for (var j = 0; j < htmlElementsLength; j++) {
              document.querySelector(self.selector).appendChild(htmlElements[j]);
            }
          }

          self.initializeSearch();
          resolve(document.querySelector(self.selector));
        }
      });
    }
    /**
     * Initialize search functionality on the ul this searchable does its job for
     */

    /**
     * Initialize search functionality on the ul this searchable does its job for
     */

  }, {
    key: "initializeSearch",
    value: function initializeSearch() {
      var _this = this;

      var section = this.section;
      var input = document.querySelector(this.inputSelector);
      var searchUl = document.querySelector(this.selector);
      var resultCounter = document.getElementById(this.resultCounterId); //handles searching

      input.addEventListener('keyup', function (event) {
        var mainUl = document.getElementById(_this.mainUlId);
        var resultsCount = 0;
        var filterValue = input.value.toLowerCase();
        var noSearchValue = filterValue == '' ? true : false;
        var listItems = searchUl.querySelectorAll('li');
        var listItemsCount = listItems.length; // console.log(listItemsCount);

        for (var i = 0; i < listItemsCount; i++) {
          var itemValue = listItems[i].dataset.title.toLowerCase();
          var itemModel = JSON.parse(listItems[i].dataset.model);
          var foundInTitle = itemValue.indexOf(filterValue) > -1 && noSearchValue === false;
          var foundInModel = false;

          if (!foundInTitle && filterValue.length >= 3) {
            //Only search when the length of the filter value is 3 or more to filter out crap
            for (var property in itemModel) {
              if (!itemModel.hasOwnProperty(property)) continue;

              if (String(itemModel[property]).toLowerCase().indexOf(filterValue.toLowerCase()) !== -1) {
                foundInModel = true;
                break;
              }
            }
          }

          if (foundInTitle || foundInModel) {
            //item found
            resultsCount++;
            listItems[i].classList.add(_this.visibleClass);
            listItems[i].setAttribute('dusk', 'found_search_item');
          } else {
            //item not found
            listItems[i].classList.remove(_this.visibleClass);
            listItems[i].removeAttribute('dusk');
          }
        }

        if (resultsCount > 0) {// searchUl.parentNode.classList.add(this.visibleClass);
          // mainUl.classList.add(this.invisibleClass);
        } else {// searchUl.parentNode.classList.remove(this.visibleClass);
            // mainUl.classList.remove(this.invisibleClass);
          }

        resultCounter.innerHTML = resultsCount + "";

        if (!noSearchValue) {
          section.classList.add(_this.visibleClass);
          mainUl.classList.add(_this.invisibleClass);
        } else {
          section.classList.remove(_this.visibleClass);
          mainUl.classList.remove(_this.invisibleClass);
        }
      });
      searchUl.classList.remove(this.visibleClass);
    }
    /**
     * Creates a menu item (HTMLElement) and sub menu items if necessary
     *
     * @param data
     * @param items array Used internally. Humans must not touch this
     * @param currentTreeLevel string Used internally. Humans must not touch this
     * @returns {Array}
     */

  }, {
    key: "createHtmlElement",
    value: function createHtmlElement(data) {
      var items = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
      var currentTreeLevel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';

      if (this.initialized === false) {
        console.error('Please initialize the controller with the init method first.');
        return;
      }

      var self = this;
      var activeId = self.activeId;
      var id = data.id;
      var title = data.title;
      var model = data.model;
      var children = data.children;
      var status = data.status;
      var thumbnail = data.thumbnail;
      var breadcrumb = currentTreeLevel;
      var treeBreadcrumb = currentTreeLevel !== "" ? currentTreeLevel + " | " + title : title; // console.log(breadcrumb);
      // console.log(data);
      //Render all child html items first

      var childItems = [];
      var _iteratorNormalCompletion = true;
      var _didIteratorError = false;
      var _iteratorError = undefined;

      try {
        for (var _iterator = children[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
          var object = _step.value;
          childItems.push(this.createHtmlElement(object, items, treeBreadcrumb));
        } //Displays a red or green line in front of the item depending on if the status (class) is active or not

      } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion && _iterator.return != null) {
            _iterator.return();
          }
        } finally {
          if (_didIteratorError) {
            throw _iteratorError;
          }
        }
      }

      var colorStatusHtml = "\n            <span class=\"color-status\" data-status-type=\"".concat(status, "\">\n                &nbsp;\n            </span>\n        "); //Displays the items icon thumbnail OR the first character of its title

      var iconHtml = "\n            <div class=\"icon\" ".concat(thumbnail ? "style=\"background-image: url('".concat(thumbnail, "');\"") : '', " >\n                ").concat(thumbnail ? '' : "<span>".concat(title ? title.substring(0, 1) : "", "</span>"), "\n            </div>\n        "); //The main item html that has all other items

      var listIem = "\n            <li data-title=\"".concat(title, "\" data-model='").concat(JSON.stringify(model) || JSON.stringify({}), "' class=\"").concat(this.listItemClass, " ").concat(id == activeId ? 'active' : '', "\"> \n                <a href=\"").concat(this.editEntitiesUrl, "/").concat(id, "\">                   \n                    ").concat(colorStatusHtml, "\n                    ").concat(iconHtml, "\n                    <p data-breadcrumb=\"").concat(breadcrumb, "\">").concat(title, "</p>\n                </a>\n            </li> \n        "); //Render it to a real html element

      var domParser = new DOMParser();
      var document = domParser.parseFromString(listIem, "text/html");
      items.push(document.body.firstChild); // console.log('rendered item: ');
      // console.log(items);
      //And then add the children inside

      var childrenLength = childItems.length;

      if (childrenLength > 0) {
        for (var i = 0; i < childrenLength; i++) {
          var child = childItems[i];
          items.push(child[0]);
        }
      } // console.log('items result:');
      // console.log(items);
      //and return it


      return items;
    }
  }]);

  return SearchController;
}();
/**
 * Fills an ul element with data retrieved from an api and makes the items draggable so that you can sort them.
 * Also updates the api with the new positions of the items. The data to and from the api has this structure for example.
 *
 * [
 *  {
 *      id:1
 *      title:false
 *      thumbnail:false
 *      status: "active"
 *      routes: []
 *      children: [
 *          {
 *              id: 12
 *              title: "Thuis"
 *              thumbnail: false
 *              routes: [{
 *                  40: "en/Homenew",
 *                  104: "nl/Thuisnew"
 *              }]
 *          }
 *      ]
 *  }
 * ]
 */


var SortableController =
/*#__PURE__*/
function () {
  function SortableController(selector) {
    _classCallCheck(this, SortableController);

    this.apiUrl = '';
    this.editEntitiesUrl = '';
    this.initialized = false;
    this.selector = selector;
    this.disabled = true;
    this.listItemClass = 'entities-list-item';
    var rootUl = document.querySelector(this.selector);
    this.siteSlug = rootUl.dataset.siteSlug;
    this.slug = rootUl.dataset.slug;
    this.activeId = rootUl.dataset.activeId;
    axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
  }
  /**
   * Initializes the controller so that it knows where it can get its data from,
   * where it needs to direct users when they click on an item and from which ul it
   * should create a sortable ul
   *
   * @param apiUrl A string
   * @param editEntitiesUrl A string
   */


  _createClass(SortableController, [{
    key: "init",
    value: function init(apiUrl, editEntitiesUrl) {
      this.apiUrl = apiUrl;
      this.editEntitiesUrl = editEntitiesUrl;
      var itemsThatHaveSubUl = document.querySelectorAll(this.selector + " li ul");
      var itemsThatHaveSubUlLength = itemsThatHaveSubUl.length;

      for (var i = 0; i < itemsThatHaveSubUlLength; i++) {
        var node = itemsThatHaveSubUl[i];
        node.style.display = node.style.display !== 'none' ? 'none' : '';
      }

      this.initialized = true;
    }
  }, {
    key: "updateSortableJavascript",
    value: function updateSortableJavascript() {
      // console.log("Updating all sortable elements with these selectors: '" + this.selector+" .sortable' AND '"+this.selector+"'");
      $('.sortable').sortable({
        connectWith: ".sortable",
        placeholder: "sortable-placeholder",
        disabled: this.disabled
      });
    }
    /**
     * Makes the rootUl sortable
     */

  }, {
    key: "enableSortable",
    value: function enableSortable() {
      if (this.initialized === false) {
        console.error('Please initialize the controller with the init method first.');
        return;
      }

      this.disabled = false;
      $(this.selector).sortable({
        disabled: this.disabled
      }).addClass('sorting');
      this.updateSortableJavascript();
    }
    /**
     * Diables the rootUl so that it cannot be sorted
     */

  }, {
    key: "disableSortable",
    value: function disableSortable() {
      // if (this.initialized === false) { console.error('Please initialize the controller with the init method first.'); return; }
      this.disabled = true;
      $(this.selector).sortable({
        disabled: this.disabled
      }).removeClass('sorting');
      this.save();
    }
    /**
     * Saves the item data to the api
     */

  }, {
    key: "save",
    value: function save() {
      if (this.initialized === false) {
        console.error('Please initialize the controller with the init method first.');
        return;
      }

      var itemsJson = this.itemsToJson(document.querySelector(this.selector));
      var rootItem = {
        id: 1,
        routes: {},
        status: null,
        thumbnail: false,
        title: null,
        children: itemsJson
      };
      itemsJson = JSON.stringify(rootItem);
      var apiJson = {
        "tree": itemsJson
      };
      axios.post(this.apiUrl, apiJson).then(function (response) {// console.log('Successfully stored the sort order to the api: ');
        // console.log(response);
      }).catch(function (error) {
        // console.error('Could not save sortable sort order to api because an error occured: ');
        console.error(error);
      });
    }
    /**
     * Converts the rootUl back to json for saving it
     *
     * @param htmlElement HTMLElement Root ul
     * @return null|[] if something went wrong null, or an array containing json items if successfull.
     */

  }, {
    key: "itemsToJson",
    value: function itemsToJson(htmlElement) {
      if (this.initialized === false) {
        console.error('Please initialize the controller with the init method first.');
        return;
      }

      var jsonArray = [];
      var error = false; //find all child li items

      var listItems = htmlElement.querySelectorAll('li.' + this.listItemClass);
      var listItemsLength = listItems.length;

      for (var i = 0; i < listItemsLength; i++) {
        var listItem = listItems[i]; //Skip children of children because they will be processed in the recursive itemsToJson call down here.

        if (listItem.parentElement !== htmlElement) continue;
        var elementJson = listItem.dataset.json;

        if (!elementJson) {
          console.error('One or more li HTMLElements with class "' + this.listItemClass + '" did not have data-json attribute set while it should.');
          error = true;
        }

        var currentItemJson = JSON.parse(listItem.dataset.json);
        var childUl = listItem.querySelector('ul');

        if (childUl) {
          currentItemJson.children = this.itemsToJson(childUl);
          if (!currentItemJson.children) error = true;
        } else {
          currentItemJson.children = [];
        }

        jsonArray.push(currentItemJson);
      }

      if (error) return null;
      return jsonArray;
    }
    /**
     * Returns a promise that resolves with the root ul that then will contain the items retrieved from the api
     */

  }, {
    key: "load",
    value: function load() {
      if (this.initialized === false) {
        console.error('Please initialize the controller with the init method first.');
        return;
      }

      self = this;
      return new Promise(function (resolve, reject) {
        if (self.initialized === false) {
          reject('Please initialize the controller with the init method first.');
        }

        axios.get(self.apiUrl).then(function (response) {
          if (!response.data || response.data.length == 0) {
            reject('The sortable did not get any data from the api');
            return;
          }

          var childrenLength = response.data.children.length;

          for (var i = 0; i < childrenLength; i++) {
            var itemObject = response.data.children[i];
            document.querySelector(self.selector).appendChild(self.createHtmlElement(itemObject));
          }

          self.updateSortableJavascript();
          resolve(document.querySelector(self.selector));
        }).catch(function (error) {
          reject(error);
        });
      });
    }
    /**
     * Removes all children from the ul
     */

  }, {
    key: "clearRootUl",
    value: function clearRootUl() {
      if (this.initialized === false) {
        console.error('Please initialize the controller with the init method first.');
        return;
      }

      var rootUl = document.querySelector(this.selector);

      while (rootUl.firstChild) {
        rootUl.removeChild(rootUl.firstChild);
      }
    }
    /**
     * Creates a menu item (HTMLElement) and sub menu items if necessary
     *
     * @param data
     * @returns {HTMLElement}
     */

  }, {
    key: "createHtmlElement",
    value: function createHtmlElement(data) {
      if (this.initialized === false) {
        console.error('Please initialize the controller with the init method first.');
        return;
      }

      self = this;
      var activeId = self.activeId;
      var id = data.id;
      var title = data.title || '-';
      var thumbnail = data.thumbnail;
      var children = data.children;
      var status = data.status;
      var routes = data.routes; //Generate json data representing that element

      var routesForElement = {};

      for (var routeProperty in routes) {
        if (!routes.hasOwnProperty(routeProperty)) continue;
        routesForElement[routeProperty] = routes[routeProperty];
      }

      if (routesForElement == {}) routesForElement = [];
      var elementJson = {
        id: data.id,
        title: data.title,
        thumbnail: data.thumbnail,
        routes: routesForElement,
        status: data.status
      };
      elementJson = JSON.stringify(elementJson); //Render all child html items first

      var childItems = [];
      var childrenLength = children.length;

      for (var index = 0; index < childrenLength; index++) {
        var obj = children[index];
        childItems.push(this.createHtmlElement(obj));
      } //Displays a red or green line in front of the item depending on if the status (class) is active or not


      var colorStatusHtml = "\n            <span class=\"color-status\" data-status-type=\"".concat(status, "\">\n                &nbsp;\n            </span>\n        "); //Displays the items icon thumbnail OR the first character of its title

      var iconHtml = "\n            <div class=\"icon\" ".concat(thumbnail ? "style=\"background-image: url('".concat(thumbnail, "');\"") : '', " >\n                ").concat(thumbnail ? '' : "<span>".concat(title ? title.substring(0, 1) : "", "</span>"), "\n            </div>\n        "); //The main item html that has all other items

      var listIem = "\n            <li data-json='".concat(elementJson, "' class=\"").concat(this.listItemClass, " ").concat(id == activeId ? 'active' : '', "\"> \n                <a href=\"").concat(this.editEntitiesUrl, "/").concat(id, "\">\n                    ").concat(colorStatusHtml, "\n                    ").concat(iconHtml, "\n                    <p>").concat(title, "</p>\n                </a>\n            </li> \n        "); //Render it to a real html element

      var domParser = new DOMParser();
      var document = domParser.parseFromString(listIem, "text/html");
      var node = document.body.firstChild;
      var childItemsLength = childItems.length; //And add the children inside

      if (childItemsLength > 0) {
        var subList = document.createElement('ul');
        subList.className = 'sortable'; // console.log('rendered childItems');
        // console.log(childItems);

        for (var _index = 0; _index < childItemsLength; _index++) {
          var element = childItems[_index];
          subList.appendChild(element);
        }

        node.appendChild(subList);
      } //and return it


      return node;
    }
  }]);

  return SortableController;
}();

var ConfirmationController =
/*#__PURE__*/
function () {
  /**
   * ConfirmationController constructor
   *
   * @param navigatableElement {HTMLElement}
   */
  function ConfirmationController(navigatableElement) {
    _classCallCheck(this, ConfirmationController);

    if (this.validateElement(navigatableElement) === false) {
      console.error('The navigatableElement isn\'t valid. Did not enable the confirmation functionality for that navigatableElement. You passed a "' + navigatableElement.tagName + '"');
      return;
    } //Set translations form dataset or an empty string if not present


    this.headerText = navigatableElement.dataset.confirmHeader ? navigatableElement.dataset.confirmHeader : '';
    this.message = navigatableElement.dataset.confirmMessage ? navigatableElement.dataset.confirmMessage : '';
    this.confirmText = navigatableElement.dataset.confirmConfirmText ? navigatableElement.dataset.confirmConfirmText : '';
    this.cancelText = navigatableElement.dataset.confirmCancelText ? navigatableElement.dataset.confirmCancelText : '';
    this.navigatableElement = navigatableElement;
    this.onlyConfirmIfTrueCallback = null; //An optional callback that must return true or false to determine if the confirmation controller must show the prompt or not for the navigatableElement

    this.confirmCallback = null; //An optional callback that is triggered when the user confirmed the action

    this.addListenersToNavigatable(this.navigatableElement);
  }
  /**
   * Adds listeners to the navigatableElement that the selector from the constructor references to.
   * So that the navigatableElement works
   *
   * @param navigatableElement
   */


  _createClass(ConfirmationController, [{
    key: "addListenersToNavigatable",
    value: function addListenersToNavigatable(navigatableElement) {
      navigatableElement.addEventListener('click', function (controller) {
        return function (clickEvent) {
          var confirm = false;
          if (controller.onlyConfirmIfTrueCallback && controller.onlyConfirmIfTrueCallback.call() === true || !controller.onlyConfirmIfTrueCallback) confirm = true;

          if (confirm) {
            clickEvent.preventDefault();
            controller.showConfirmationPrompt(true, navigatableElement);
          }
        };
      }(this));
    }
    /**
     * Sets a callback that wil be used to check if we actually need to confirm the action on the navigatableElement or just allow it.
     * When the callback returns true or if you don't specify the callback, confirmation wil be done. When false. it won't be done.
     *
     * @param onlyConfirmIfTrueCallback
     */

  }, {
    key: "setOnlyConfirmIfTrueCallback",
    value: function setOnlyConfirmIfTrueCallback(onlyConfirmIfTrueCallback) {
      this.onlyConfirmIfTrueCallback = onlyConfirmIfTrueCallback;
    }
    /**
     * Add or remove listeners to / from the modal buttons elements.
     * Usually the yes no button elements.
     */

  }, {
    key: "addListenersToModalButtons",
    value: function addListenersToModalButtons() {
      var add = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
      var originalNavigatableElement = arguments.length > 1 ? arguments[1] : undefined;
      if (!this.promptElement) console.error('First create the modal with the createPrompt method');
      var confirmButton = this.promptElement.querySelector('button.confirm');
      var cancelButton = this.promptElement.querySelector('button.cancel');
      var shader = this.promptElement.querySelector('div.shader');
      confirmButton.removeEventListener('click', this.confirmClicked.bind(this));
      cancelButton.removeEventListener('click', this.cancelClicked.bind(this));
      shader.removeEventListener('click', this.cancelClicked.bind(this));

      if (add) {
        confirmButton.addEventListener('click', this.confirmClicked.bind(this));
        cancelButton.addEventListener('click', this.cancelClicked.bind(this));
        shader.addEventListener('click', this.cancelClicked.bind(this));
      }
    }
    /**
     * Sets an optional callback that is triggered when the user confirmed the action.
     * If you don't specify it, the nearest form that is found by traversing up into the dom is submitted
     *
     * @param callback
     */

  }, {
    key: "setConfirmCallback",
    value: function setConfirmCallback(callback) {
      this.confirmCallback = callback;
      return this;
    }
    /**
     * Triggered when the user clicks the confirm button
     *
     * @param mouseEvent
     */

  }, {
    key: "confirmClicked",
    value: function confirmClicked(mouseEvent) {
      mouseEvent.preventDefault();

      if (this.confirmCallback) {
        this.confirmCallback.call();
      } else {
        //Find the nearest form by traversing up into the dom
        this.addNavigatableElementValueToForm();
        this.submitNearestForm(false);
      }

      this.showConfirmationPrompt(false);
    }
    /**
     * If the navigatable element contains a value,
     * we add a hidden input to the form with the same name and value
     * as the navigatable. Making sure that its value is passed as expected.
     */

  }, {
    key: "addNavigatableElementValueToForm",
    value: function addNavigatableElementValueToForm() {
      if (this.navigatableElement.hasAttribute('value') && this.navigatableElement.hasAttribute('name')) {
        var form = this.findForm(this.navigatableElement);
        if (!form) return;
        var input = document.createElement('INPUT');
        input.setAttribute('type', 'hidden');
        input.setAttribute('name', this.navigatableElement.getAttribute('name'));
        input.setAttribute('value', this.navigatableElement.getAttribute('value'));
        form.appendChild(input);
      }
    }
    /**
     * Submit the nearest form the navigatableElement is in,
     * by traversing up into the dome as long as no form is found
     */

  }, {
    key: "submitNearestForm",
    value: function submitNearestForm() {
      var form = this.findForm(this.navigatableElement);

      if (form) {
        form.submit();
        return true;
      } else {
        console.error('Could not submit the nearest form this navigatableElement should be in, because it isn\'t in a form.');
        return false;
      }
    }
    /**
     * Triggered when the user clicks the cancel button
     *
     * @param mouseEvent
     */

  }, {
    key: "cancelClicked",
    value: function cancelClicked(mouseEvent) {
      mouseEvent.preventDefault();
      this.showConfirmationPrompt(false);
    }
    /**
     * Retrieves an HTML element and starts traversing up into the dom to find the first form the element is in.
     * Returns the form or false if it cannot be found
     * @param element
     */

  }, {
    key: "findForm",
    value: function findForm(element) {
      if (!element.parentNode) return false;
      if (element.parentNode.tagName === 'FORM') return element.parentNode;
      return this.findForm(element.parentNode);
    }
    /**
     * Create a div that represents a prompt
     *
     * @returns {HTMLDivElement}
     */

  }, {
    key: "createPrompt",
    value: function createPrompt() {
      var html = '<div class="modal">' + '<div class="header"><h4>' + this.headerText + '</h4></div>' + '<div class="body">' + '<p class="message">' + this.message + '</p>' + '<div class="navigatableElements">' + '<button class="confirm" dusk="confirmation_confirm">' + this.confirmText + '</button>' + '<button class="cancel" dusk="confirmation_cancel">' + this.cancelText + '</button>' + '</div>' + '</div>' + '</div>' + '</div>' + '<div class="shader"></div>';
      var promptElement = document.createElement("div");
      promptElement.setAttribute('id', 'confirmBox');
      promptElement.innerHTML = html;
      return promptElement;
    }
    /**
     * Show or hides the confirmation prompt by adding a hidden class to it.
     */

  }, {
    key: "showConfirmationPrompt",
    value: function showConfirmationPrompt(show, originalNavigatableElement) {
      if (!this.promptElement) {
        this.promptElement = this.createPrompt();
        this.addListenersToModalButtons(true, originalNavigatableElement);
      }

      if (show) {
        this.promptElement.classList.add('show');
        document.body.appendChild(this.promptElement);
      } else {
        this.promptElement.classList.remove('show');

        if (this.promptElement.parentElement) {
          this.promptElement.parentElement.removeChild(this.promptElement);
        }

        this.promptElement = null;
      }
    }
    /**
     * Returns true when the navigatableElement is a navigatableElement tag or an input tag with type navigatableElement.
     * false if not
     *
     * @param navigatableElement {HTMLElement}
     * @returns {boolean}
     */

  }, {
    key: "validateElement",
    value: function validateElement(navigatableElement) {
      if (!navigatableElement) return false;
      if (navigatableElement.tagName !== 'BUTTON' && navigatableElement.tagName !== 'INPUT' && navigatableElement.tagName !== 'A') return false;

      if (navigatableElement.tagName === "INPUT") {
        if (navigatableElement.getAttribute('type').toLowerCase() !== 'navigatableElement' && navigatableElement.getAttribute('type').toLowerCase() !== 'submit') return false;
      }

      return true;
    }
    /**
     * @param text
     * @returns {ConfirmationController}
     */

  }, {
    key: "setHeaderText",
    value: function setHeaderText(text) {
      this.headerText = text;
      return this;
    }
    /**
     * @param text
     * @returns {ConfirmationController}
     */

  }, {
    key: "setMessage",
    value: function setMessage(text) {
      this.message = text;
      return this;
    }
    /**
     * @param text
     * @returns {ConfirmationController}
     */

  }, {
    key: "setConfirmText",
    value: function setConfirmText(text) {
      this.confirmText = text;
      return this;
    }
    /**
     * @param text
     * @returns {ConfirmationController}
     */

  }, {
    key: "setCancelText",
    value: function setCancelText(text) {
      this.cancelText = text;
      return this;
    }
  }]);

  return ConfirmationController;
}();
/**
 * Observes the contents of the element you reference to via the constructor selector variable
 * for added nodes and triggers callbacks for added nodes when the match the given selector that
 * you've specified with the bindSelectorToCallback method
 */


var Initializer =
/*#__PURE__*/
function () {
  /**
   * @param wrapperSelector A selector of an element that contains all elements that are bound with the bindSelectorToCallback method. As close as possible to the things they match
   */
  function Initializer(wrapperSelector) {
    _classCallCheck(this, Initializer);

    this._bindings = {};
    this._onceBindings = {}; //Selectors that may only be initialized once if the binding in this object is true

    this._booted = false;
    this._observer = null;
    this._isObserving = false;
    this._showDebugInformation = false;
    this._observerConfiguration = {
      // attributeFilter: [],              //An array of specific attribute names to be monitored. If this property isn't included, changes to all attributes cause mutation notifications. No default value.
      // attributeOldValue: false,         //Set to true to record the previous value of any attribute that changes when monitoring the node or nodes for attribute changes.
      // attributes: true,                //Set to true to watch for changes to the value of attributes on the node or nodes being monitored. The default value is false.
      // characterDataOldValue: true,      //Set to true to record the previous value of a node's text whenever the text changes on nodes being monitored.
      // characterData: true,              //Set to true to monitor the specified target node or subtree for changes to the character data contained within the node or nodes. No default value.
      subtree: true,
      //Set to true to extend monitoring to the entire subtree of nodes rooted at target. All of the other MutationObserverInit properties are then extended to all of the nodes in the subtree instead of applying solely to the target node. The default value is false.,
      childList: true //Set to true to monitor the target node (and, if subtree is true, its descendants) for the addition or removal of new child nodes. The default is false.

    };
    this._wrapper = document.querySelector(wrapperSelector);

    if (!this._wrapper) {
      console.info('The selector "' + wrapperSelector + '" does not match any element. Could not monitor html elements and initialize them when needed.');
      return;
    }

    this._boot();
  }
  /**
   * Configure the Initializer to observe the element that wrapperSelector references
   * for new HTMLElements, referenced by the bound selectors. So that when they are found, the callback is called.
   * You need to call startObserving to start the observation.
   */


  _createClass(Initializer, [{
    key: "_boot",
    value: function _boot() {
      if (this._booted) return;
      this._booted = true;
      this._observer = new MutationObserver(this._mutationsObserved.bind(this));
    }
    /**
     * Start observing for changes
     *
     * @return {Initializer}
     */

  }, {
    key: "startObserving",
    value: function startObserving() {
      if (!this._booted) return this;
      if (this._showDebugInformation) console.log('Starting to observe');

      this._observer.takeRecords(); //Take the mutation records out of the observer so that it is cleared


      this._observer.observe(this._wrapper, this._observerConfiguration);

      this._isObserving = true;
      return this;
    }
    /**
     * Stop observing for changes
     *
     * @return {Initializer}
     */

  }, {
    key: "stopObserving",
    value: function stopObserving() {
      if (!this._booted) return this;
      if (this._showDebugInformation) console.log('Stopped to observe');

      this._observer.disconnect();

      this._isObserving = false;
      return this;
    }
    /**
     * Triggered by the MutationObserver when a mutation had taken place
     *
     * @param {MutationRecord[]} mutationsList
     */

  }, {
    key: "_mutationsObserved",
    value: function _mutationsObserved(mutationsList) {
      if (!this._booted) return this;
      var mutationsCount = mutationsList.length;
      if (this._showDebugInformation) console.info('Detected ' + mutationsCount + ' changes');

      for (var mutationNumber = 0; mutationNumber < mutationsCount; mutationNumber++) {
        var mutationRecord = mutationsList[mutationNumber];
        var addedNodes = mutationRecord.addedNodes;
        var addedNodesCount = addedNodes.length;

        for (var addedNodeNumber = 0; addedNodeNumber < addedNodesCount; addedNodeNumber++) {
          var addedNode = addedNodes[addedNodeNumber];

          this._triggerBoundCallbacksIfElementMatchesSelector(addedNode);
        }
      }
    }
    /**
     * @param {HTMLElement} htmlElement
     */

  }, {
    key: "_triggerBoundCallbacksIfElementMatchesSelector",
    value: function _triggerBoundCallbacksIfElementMatchesSelector(htmlElement) {
      for (var selector in this._bindings) {
        // if(this._showDebugInformation) console.log('Checking if selector "'+selector+'" matches HTMLElement', htmlElement);
        var addedElementMatchesSelector = htmlElement.matches(selector);
        var elementsThatMatch = htmlElement.querySelectorAll(selector);
        var matchingElementsCount = elementsThatMatch.length;

        if (addedElementMatchesSelector || matchingElementsCount > 0) {
          if (addedElementMatchesSelector) {
            if (!htmlElement.hasAttribute('initialized') || this._onceBindings[selector] === false) {
              if (this._showDebugInformation) console.log('Calling callback for selector "' + selector + '". HTMLElement', htmlElement);

              this._bindings[selector](this, htmlElement);

              htmlElement.setAttribute('initialized', '');
            }
          }

          if (matchingElementsCount > 0) {
            for (var currentMatchingElementIndex = 0; currentMatchingElementIndex < matchingElementsCount; currentMatchingElementIndex++) {
              var currentMatchingElement = elementsThatMatch[currentMatchingElementIndex];

              if (!currentMatchingElement.hasAttribute('initialized') || this._onceBindings[selector] === false) {
                if (this._showDebugInformation) console.log('Calling callback for selector "' + selector + '". HTMLElement', currentMatchingElement);

                this._bindings[selector](this, currentMatchingElement);

                currentMatchingElement.setAttribute('initialized', '');
              }
            }
          }
        }
      }
    }
    /**
     * @param {string} selector
     * @param {function} callback
     * @param once
     * @return {Initializer}
     */

  }, {
    key: "bindSelectorToCallback",
    value: function bindSelectorToCallback(selector, callback) {
      var once = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
      if (!this._booted) return this; //Register the selector and callback

      if (typeof selector !== 'string') {
        console.error('Initializer:bind The selector must be a string');
        return this;
      }

      if (typeof callback !== 'function') {
        console.error('Initializer:bind The callback must be a function');
        return this;
      }

      if (typeof once !== 'boolean') {
        console.error('Initializer:bind The once variable must be a boolean');
        return this;
      }

      this._bindings[selector] = callback;
      this._onceBindings[selector] = once;
      if (this._showDebugInformation) console.log('bound selector "' + selector + '" to a callback'); //Trigger existing matches. Temporary stops the observer to prevent double callback calling.

      var wasObserving = this._isObserving;
      if (this._isObserving) this.stopObserving();

      var nodeList = this._wrapper.querySelectorAll(selector);

      if (!nodeList) return this;
      var length = nodeList.length;

      for (var currentElementNumber = 0; currentElementNumber < length; currentElementNumber++) {
        callback(this, nodeList[currentElementNumber]);
      }

      if (wasObserving) this.startObserving();
      return this;
    }
  }]);

  return Initializer;
}();
/**
 * Tracks all inputs, selects and textareas in the given wrapper element for changes.
 * If the user clicked an button, submit input or an anchor the user fist must confirm that he's going to lose changes.
 */


var PreventNavigationController =
/*#__PURE__*/
function () {
  /**
   * inputs in the wrapper element will be tracked for changes
   *
   * @param WrapperElement {Element}
   */
  function PreventNavigationController(WrapperElement) {
    _classCallCheck(this, PreventNavigationController);

    //Create properties
    this.inputs = []; //Inputs, textareas, selects

    this.wrapperElement = null;
    this.translation = {
      headerText: '',
      message: '',
      confirmText: '',
      cancelText: ''
    };
    this.changed = false; //Automatically set to true when one of the inputs was changed
    //validate stuff

    if (!WrapperElement) {
      console.warn('No wrapper element given. Not preventing navigation.');
      return;
    }

    if (!WrapperElement.dataset.translation) {
      console.warn('No translation present. Not preventing navigation when not all changes have been saved.');
      return;
    }

    this.wrapperElement = WrapperElement; //Delegate control to specialist parts of the class

    this.loadTranslation();
    this.inputs = this.findAllInputsIn(WrapperElement);
    this.interceptClicksOnNavigatableElements();
    this.addListenersToInputs(this.inputs);
  }
  /**
   * Returns true if the given input element is an HTMLElement of tag Input.
   *
   * @param InputElement {HTMLElement}
   * @returns {boolean}
   */


  _createClass(PreventNavigationController, [{
    key: "isTrackableElement",
    value: function isTrackableElement(InputElement) {
      return InputElement.tagName === "INPUT" || InputElement.tagName === "SELECT" || InputElement.tagName === "TEXTAREA";
    }
    /**
     * Add listeners to inputs
     *
     * @param inputs {array}
     * @param add {boolean}
     */

  }, {
    key: "addListenersToInputs",
    value: function addListenersToInputs(inputs) {
      var add = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      var nInputs = inputs.length;

      for (var currentInputNumber = 0; currentInputNumber < nInputs; currentInputNumber++) {
        if (add) {
          inputs[currentInputNumber].addEventListener('change', this.inputChanged.bind(this));
        } else {
          inputs[currentInputNumber].removeEventListener('change', this.inputChanged.bind(this));
        }
      }
    }
    /**
     * Triggered in response to a changed input
     *
     * @param event
     */

  }, {
    key: "inputChanged",
    value: function inputChanged(event) {
      this.changed = true;
      console.log(this.changed);
    }
    /**
     * Loads the translations. They are defined on the wrapper element
     */

  }, {
    key: "loadTranslation",
    value: function loadTranslation() {
      this.translation = JSON.parse(this.wrapperElement.dataset.translation);
    }
    /**
     * Makes sure that clicks on links are intercepted and need to be confirmed first
     *
     * @param enable {boolean}
     */

  }, {
    key: "interceptClicksOnNavigatableElements",
    value: function interceptClicksOnNavigatableElements() {
      var _this2 = this;

      var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
      var links = document.getElementsByTagName('A');
      var nLinks = links.length;

      var _loop = function _loop(linkNumber) {
        var currentLink = links[linkNumber];
        var linkHref = currentLink.getAttribute('href');

        if (linkHref && linkHref.substr(0, 1) !== "#") {
          new ConfirmationController(currentLink).setHeaderText(_this2.translation.headerText).setMessage(_this2.translation.message).setConfirmText(_this2.translation.confirmText).setCancelText(_this2.translation.cancelText).setConfirmCallback(function () {
            window.location = linkHref;
          }).setOnlyConfirmIfTrueCallback(function (controller) {
            return function () {
              return controller.hasChanged();
            };
          }(_this2));
        }
      };

      for (var linkNumber = 0; linkNumber < nLinks; linkNumber++) {
        _loop(linkNumber);
      }
    }
    /**
     * Returns true if one of the input has changed
     * @returns {boolean}
     */

  }, {
    key: "hasChanged",
    value: function hasChanged() {
      return this.changed;
    }
    /**
     * Finds all html elements witch match elements specified in the isTrackableElement method
     *
     * @param WrapperElement {Element}
     * @param inputs
     * @returns {Array}
     */

  }, {
    key: "findAllInputsIn",
    value: function findAllInputsIn(WrapperElement) {
      var inputs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
      var nChildren = WrapperElement.children.length;
      if (nChildren === 0) return inputs;

      for (var index = 0; index < nChildren; index++) {
        var currentChild = WrapperElement.children[index];

        if (this.isTrackableElement(currentChild)) {
          inputs.push(currentChild);
        }

        if (currentChild.children.length > 0) {
          var childInputs = this.findAllInputsIn(currentChild, inputs);
          inputs.concat(childInputs);
        }
      }

      return inputs;
    }
  }]);

  return PreventNavigationController;
}();

var TabsController =
/*#__PURE__*/
function () {
  /**
   * The tab controller can obviously control tabs.
   * You just have to have a couple of divs that hold the content. These divs must all have a class name that
   * corresponds to the value of constructor parameter tabContentIdAndClassAndPrefix. And they all must have an id
   * that also starts with the value of tabContentIdAndClassAndPrefix followed by the tab slug.
   *
   * You can specify if you have an hidden input field that needs to be updated with the curent tab slug. You do that
   * with the tabSlugInputSelector.
   *
   * Content tab divs and buttons will also receive an active state class to make them visible / stand out when present
   * or hidden / to background. You can specify this class name with the activeClass parameter.
   *
   * The tabButtonGroupSelector selects an element that holds the tab buttons to switch tabs. This element must have an
   * ul element that holds li elements containing a elements.
   *
   * The reactToUrlHashChange parameter controls if the controller should react if the hash part of the url did change.
   *
   * @param tabContentIdAndClassAndPrefix string
   * @param tabButtonGroupSelector string
   * @param activeClass string
   * @param reactToUrlHashChange
   * @param tabSlugInputSelector string
   */
  function TabsController() {
    var tabContentIdAndClassAndPrefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'tab';
    var tabButtonGroupSelector = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '.tab-buttons';
    var activeClass = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'active';
    var reactToUrlHashChange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
    var tabSlugInputSelector = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined;

    _classCallCheck(this, TabsController);

    var input = document.querySelector(this.tabSlugInputId);
    this.tabButtonGroupSelector = tabButtonGroupSelector;
    this.tabContentDivsClassAndIdPrefix = tabContentIdAndClassAndPrefix;
    this.tabSlugInputId = tabSlugInputSelector;
    this.activeClass = activeClass;
    this.reactToUrlHashChange = reactToUrlHashChange;
    if (reactToUrlHashChange) this.addListenerForHashChange(reactToUrlHashChange);
  }
  /**
   * Opens the tab by using the tab slug
   *
   * @param tabSlug
   */


  _createClass(TabsController, [{
    key: "openTab",
    value: function openTab(tabSlug, clearStorage) {
      //Remove trailing / on the left hand side
      tabSlug = this.removeLeftHandSlashInSlug(tabSlug);

      if (!tabSlug) {
        return;
      }

      if (clearStorage) {
        console.log('clear session storage');
        sessionStorage.clear();
      }

      this.updateTabSlugInput(tabSlug);
      this.showTabContentForTabWithSlug(tabSlug);
      this.makeTabButtonActiveForSlug(tabSlug);
    }
    /**
     * Removes a / at the beginning of a tab slug
     *
     * @param tabSlug
     */

  }, {
    key: "removeLeftHandSlashInSlug",
    value: function removeLeftHandSlashInSlug(tabSlug) {
      return tabSlug.replace(/^\/(.*)/, '$1');
    }
    /**
     * Updates a usually hidden input field holding the tab slug with a new slug
     *
     * @param newSlug string
     */

  }, {
    key: "updateTabSlugInput",
    value: function updateTabSlugInput(newSlug) {
      if (this.tabSlugInputId === undefined) return;
      var element = document.querySelector(this.tabSlugInputId);
      if (element) element.value = newSlug;
    }
  }, {
    key: "makeTabButtonActiveForSlug",
    value: function makeTabButtonActiveForSlug(slug) {
      var entityTabs = document.querySelectorAll('.entity-tabs > ul > li');
      var nTabs = entityTabs.length;

      for (var index = 0; index < nTabs; index++) {
        var currentTab = entityTabs[index];
        currentTab.classList.remove('active');
      }

      var activeTab = document.querySelector('.entity-tabs > ul > li a[href="#' + slug + '"]');
      activeTab.parentElement.classList.add('active');
    }
    /**
     * Shows the tab content div with the specified slug and hides the other content div tabs.
     * It does this by adding and removing classes (the active class you specified in the constructor)
     *
     * @param slug string
     */

  }, {
    key: "showTabContentForTabWithSlug",
    value: function showTabContentForTabWithSlug(slug) {
      //Remove the active class from all tab content classes
      var items = document.querySelectorAll('.' + this.tabContentDivsClassAndIdPrefix);
      var length = items.length;

      for (var index = 0; index < length; index++) {
        var element = items[index];
        element.classList.remove(this.activeClass);
      } //Add the active class to the tab that has the correct slug appended to the IdPrefix


      var activeTab = document.querySelector("#" + this.tabContentDivsClassAndIdPrefix + "-" + slug);

      if (!activeTab) {
        console.error("TabsController: Could not make content tab active. It should have an ID with: #" + this.tabContentDivsClassAndIdPrefix + "-" + slug);
        return;
      }

      activeTab.classList.add(this.activeClass);

      if (!isset(sessionStorage.getItem("componentScrollPosition"))) {
        activeTab.parentElement.scrollTop = 0;
      }

      activeTab.parentElement.addEventListener('scroll', function (ev) {
        sessionStorage.componentScrollPosition = ev.currentTarget.scrollTop;
      });
    }
    /**
     * Adds or disables listening for hashchange events to update tabs
     *
     * @param boolean
     */

  }, {
    key: "addListenerForHashChange",
    value: function addListenerForHashChange(boolean) {
      if (boolean) {
        window.addEventListener('hashchange', this.hashChanged.bind(this));
        window.addEventListener('load', this.hashChanged.bind(this));
      } else {
        window.removeEventListener('hashchange', this.hashChanged);
        window.removeEventListener('load', this.hashChanged);
      }
    }
    /**
     * Called automatically by an internal listener (controlled by the addListenerForHashChange method)
     */

  }, {
    key: "hashChanged",
    value: function hashChanged(event) {
      var tabSlug = window.location.hash.substring(1);

      if (tabSlug) {
        this.openTab(tabSlug, true);
        return;
      }

      var tabSlugElement = document.querySelector(this.tabSlugInputId);
      if (!tabSlugElement) return;
      this.openTab(tabSlugElement.value, false);
    }
  }]);

  return TabsController;
}();